protection of NSS DB content


This document describes how Directory Server will protect NSS database access. Using Keyring or Clevis/Tang we can prevent NSS sensitive files (passwords, extracted keys and certificates) to be compromised.

Overview

Directory servers installation contains some sensitive files. Relying on the rights of the files looks as a weak protection in case of an attack. The idea is either to remove those files or to make the content of those files useless if compromised. This document details two different approaches Keyring and Clevis/Tang.

Use Cases

DS is configured with secure port. The administrator wants DS be start without being prompted for NSS password. To do So he creates a pin file (pin.txt) that is used to initialize the NSS database and extract key/certs. Someone connected on the Directory server host, with the appropriate rights, can use the pin.txt file to read/write NSS database.

Design


Directory server is a service of systemd, so if it terminates abrutly (a crash) systemd may restart it automatically. In such case the administrator does not want to be prompted for a NSS password and so registers the NSS password in pin.txt file. In order to protect the file we evaluate two options:

Several components are impacted with this change:

Svrcore

principle

Directory servers retrieves NSS password using svrcore framework. This framework call a retrieving method and if the method fails then it calls a fallback. The fallback also registers a method/fallback etc.. Svrcore basically contains a ordered list of retrieval method and fallback. Each method/fallback is registered in a so called plugin. Each DS instance has its own svrcore list method/fallback. The ordered list of retrieval method is:

New plugin

DS retrieves NSS password using svrcore. In order to take into account a new retrieval method (keyring or Clevis/Tang) we need to create a new svrcore plugin (keyring or clevisTang). The plugin defines the retrieval method (using standard callback getPin) and insert it at the appropriate place in the retrieval method/fallback ordered list. With keyring the plugin method is in keyring-ask-password.c and the insertion in std-keyring.c. With ClevisTang the plugin method is in clevistang-ask-password.c and the insertion in std-clevistang.c.

Using keyring or alternatively ClevisTang the resulting ordered list is

setup / getPin

Because the password is stored while being root and needed while being <nsslapd-localuser> (aka as dirsrv) it requires an intermediate step. The password is stored once prompted by systemd. Before the DS deamon calls setuid (detach), DS running as root retrieves the password using keyctl_search/keyctl_read and stores it in a local variable. Then DS starts running as dirsrv and copy the password from the local variable to svrcore keyring plugin during svrcore_setup. Finally when DS needs the password, for NSS/SSL initialization, it calls svrcore getPin (during slapd_ssl_init/slapd_pk11_authenticate.

Keyring

provisioning

After a reboot of a box hosting the directory server, the keyring does not contain any data. To be provisioned, the first time the directory instance is started (via systemd), the system administrator is prompted (systemd-ask-password) for the NSS password. Then the password is stored (in clear text) in keyring.

At this time the administrator is logged as root and stores the password in ‘@u’ keyring with ‘user’ keytype.

retrieval

Later the password is retrieved by directory server (using svrcore and keyring plugin).

An important point is that keyring provisioning is done by systemd so by root user. The retrieval is done by directory server, that is launched as root but later setuid to <nsslapd-localuser> (aka as dirsrv).

key name

Keyring is a shared repository, so it will contains all the NSS passwords of all instances running on the box. The keyname must differentiate each individual instance. So the keyname has the format: <fixed name><instance_serverid><info_type>, where

Core server

using keyring

It exists two phases that register and later retrieve the password:

If the core server (main.c) uses keyring then it requires the link option -lkeyutils and define build option -DWITH_KEYRING. Indeed core server calls keyctl_search/keyctl_read to retrieve the password from keyring. It does this while the DS deamon is running as root (before detach). When retrieved, it provides the password to NSS/SSL setup rountine (slapd_do_all_nss_ssl_init). This routine first registers (svrcore_setup) the password into the svrcore plugin that handle keyring (std-keyring.c) then later retrieved from svrcore (getPin) during slapd_ssl_init/slapd_pk11_authenticate.

In the first phase, when DS started by systemd retrieves password from keyring, it calls keyctl_read that triggers a Selinux AVC. A new policy is required TBD.

using Clevis/Tang

The idea would be to let a systemd script (in systemd template ExecStartPre) to test if it exists encrypted_pin.txt JSON file. If it does not exist either prompt or read the pin.txt file, encode the password, store it into encrypted_pin.txt and remove pin.txt file.

Tang server

We need a tang server to encrypt and decrypt. If each host has its local own Tang server it is a bit generous. The advantage is it simplifes the process of key rotation and only local instance are impacted in case of problem on the Tang server. If we have a centralized Tang server, it becomes a SPOF and its key rotation will impact all instance using it. It requires to

Clevis client

The Clevis client is used to translate a clear text password file pin.txt into an encrypted one: clevis encrypt tang ‘{“url”, “http://<tang_server_hostname>[:<tang_server_ListenStream>]”}’ < pin.txt > encrypted_pin.txt.

systemd

With keyring a script must fetch (keyctl search @u user <key_name>) the NSS instance password. If it does not exist, it must prompt (systemd-ask-password) the administrator and store it (keyctl padd user <key_name> @u).

To allow DS to read the keyring password (keyctl_read), the systemd template must define KeyringMode=shared

Selinux

When the core server, running as root, reads keyring (keyctl_read) it triggers an Selinux AVC. Need to define a policy to allow that TBD

The proposed solution. This may include but is not limited to:

-   new schema
-   syntax of commands
-   logic flow
-   access control considerations

Implementation
--------------

Any additional requirements or changes discovered during the implementation phase.

Major configuration options and enablement
------------------------------------------

Any configuration options? Any commands to enable/disable the feature or turn on/off its parts?

Replication
-----------

Any impact on replication?

Updates and Upgrades
--------------------

Any impact on updates and upgrades?

Dependencies
------------

Any new package and library dependencies.

External Impact
---------------

Impact on other development teams and components

Origin
-------------

A link to the trac ticket or bugzilla

Author
------

<you@redhat.com>
Last modified on 18 October 2019