SYNOPSIS
nvme-keysd [--config=<FILE>] [--fabrics-config=<FILE>]
[--creds-dir=<DIR>] [--kmip-test-addr=<PATH>]
[--should-start] [--debug] [--help]
DESCRIPTION
nvme-keysd puts the TLS pre-shared keys (PSKs) used by NVMe/TCP into the kernel’s .nvme keyring, before a connection needs them. The kernel then finds the key there when nvme connect or nvme-discoverd connects with TLS.
Which key belongs to which host and subsystem is configured in the shared NVMe-oF fabrics configuration, see nvme-fabrics.conf(5).
This is a technology preview.
KEYS
nvme-keysd imports every entry of the fabrics configuration that has tls-key-source = systemd-creds or tls-key-source = kmip. With systemd-creds, tls-key is the name of a systemd credential. The credential holds the PSK in the PSK interchange format (NVMeTLSkey-1:<hmac>:<base64>:), as created by nvme keys gen-tls-psk.
nvme-keysd puts the PSK in the keyring named by keyring (default .nvme). The key identity is built from the host NQN and the subsystem NQN, as nvme connect does. A key that is already there is not written again. Any other key for the same host NQN and subsystem NQN is revoked, so that the kernel finds only one key for the pair.
Without a kmip entry, nvme-keysd imports the keys and exits. With a kmip entry, it keeps running: see KMIP. nvme-keysd never revokes a key because its entry was removed from the configuration.
The unit does not start when no entry of the fabrics configuration has a tls-key-source other than inline. In that case, nvme-keysd does not run, and the unit does not load the nvme_keyring module.
CREDENTIALS
Each credential is a file in /usr/local/etc/nvme/creds/, encrypted with systemd-creds(1). The directory is installed with mode 0700. The file name is the credential name. nvme-keysd decrypts the file through systemd-creds, which checks that the name in the credential is the file name. When --name is not given, systemd-creds takes the name from the output file name:
# systemd-creds encrypt psk.txt /usr/local/etc/nvme/creds/vol1-psk
and in nvme-fabrics.conf:
[Subsystem]
nqn = nqn.2024-01.com.example:storage.vol1
controller = transport=tcp;traddr=192.0.2.10;trsvcid=4420
tls = true
tls-key-source = systemd-creds
tls-key = vol1-psk
After adding or changing credentials, restart nvme-keysd to import them:
# systemctl restart nvme-keysd
nvme-keysd logs an error for a credential that it cannot decrypt, and imports the other keys.
nvme-keysd needs systemd 257 or later.
KMIP
With tls-key-source = kmip:<name>, nvme-keysd gets the PSK from a key management server (KMS) that supports KMIP 1.4. <name> is a [kmip:<name>] section of nvme-keysd.conf. When only one KMS is configured, tls-key-source = kmip is enough. tls-key is the Name of the key on the KMS.
The key on the KMS is one of:
-
Secret Data that holds the PSK in the PSK interchange format.
-
A Symmetric Key of 32 bytes (SHA-256) or 48 bytes (SHA-384).
Only a key in the Active state is used. Two Active keys with the same Name are an error.
nvme-keysd itself has no network access. For privilege separation, a helper process with no privileges handles all communication with the KMS, over TLS. A client certificate is used when one is configured. The helper logs its errors in the journal, under the identifier nvme-keysd-kmip.
The servers of a KMS are nodes of one cluster, and hold the same keys. They are tried in order, until one answers. Different KMSes are asked in parallel.
nvme-keysd does not delay the boot for a KMS. The services that start after nvme-keysd find the keys from systemd credentials in the keyring, but a KMIP key can come later. nvme-keysd keeps running and gets the KMIP keys in the background. When it cannot get a key, it tries again after 5 seconds, then after twice the previous delay, up to 5 minutes. A connection that needs a KMIP key can therefore start before the key is in the keyring. nvme-discoverd connects again later. A single nvme connect does not.
Setup example. The client private key is a systemd credential in /usr/local/etc/nvme/creds/kmip/. systemd gives it to the helper as kmip_<file>, so --name must be kmip_ and the file name:
# systemd-creds encrypt --name=kmip_my-client-key client-key.pem \
/usr/local/etc/nvme/creds/kmip/my-client-key
The CA and the client certificate are not secret. They must be readable by any user, because the helper runs without privileges. In nvme-keysd.conf:
[kmip:my-kms]
server = kms1.example.com
server = kms2.example.com
ca = /usr/local/etc/nvme/kmip/ca.pem
client-cert = /usr/local/etc/nvme/kmip/client.pem
client-key = my-client-key
and in nvme-fabrics.conf:
[Subsystem]
nqn = nqn.2024-01.com.example:storage.vol1
controller = transport=tcp;traddr=192.0.2.10;trsvcid=4420
tls = true
tls-key-source = kmip:my-kms
tls-key = my-vol1-psk
OPTIONS
- -c <FILE>
- --config=<FILE>
-
Use <FILE> instead of /usr/local/etc/nvme/nvme-keysd.conf.
- --fabrics-config=<FILE>
-
Read the fabrics configuration from <FILE> instead of /usr/local/etc/nvme/nvme-fabrics.conf.
- --creds-dir=<DIR>
-
Read the encrypted credentials from <DIR> instead of /usr/local/etc/nvme/creds.
- --kmip-test-addr=<PATH>
-
Connect to the nvme-keysd-kmip Varlink socket at <PATH> instead of /run/nvme/keysd/kmip. For tests.
- --should-start
-
Exit with status 0 if an entry of the fabrics configuration has a tls-key-source other than inline, and with status 1 otherwise. The unit runs this check before it starts nvme-keysd.
- -d
- --debug
-
Enable debug-level logging for both nvme-keysd and the libnvme calls it makes, overriding the configured debug-level.
- -h
- --help
-
Print usage and exit.
CONFIGURATION
nvme-keysd.conf holds the daemon’s own settings, in a [Global] section, and the KMSes, in [kmip:<name>] sections:
[Global]
debug-level = info
debug-level (err, warn, info, or debug; default info) sets the log threshold. --debug on the command line overrides it.
Each [kmip:<name>] section describes a KMS:
- server
-
Host name or IP address. Required. Repeat it for each server of the cluster.
- port
-
TCP port of the servers. Default 5696.
- ca
-
CA certificate that signed the server certificates (PEM). Default: the system CAs.
- client-cert
-
Client certificate (PEM). Requires client-key.
- client-key
-
File name of the client private key in /usr/local/etc/nvme/creds/kmip/. Requires client-cert.
- timeout
-
Time limit for one server: connect, TLS handshake and requests. Default 10s. Each TCP connect fails after 3 seconds at most.
A missing file, or a missing key, keeps the default.
FILES
- /usr/local/etc/nvme/nvme-keysd.conf
-
The daemon’s own configuration; see CONFIGURATION.
- /usr/local/etc/nvme/nvme-keysd.conf.sample
-
A commented example of nvme-keysd.conf with every setting at its default. It is not read; copy it to nvme-keysd.conf to change a setting.
- /usr/local/etc/nvme/creds/
-
The encrypted credentials; see CREDENTIALS.
- /usr/local/etc/nvme/creds/kmip/
-
The encrypted client private keys for the KMSes; see KMIP.
SEE ALSO
nvme-fabrics.conf(5) systemd-creds(1) nvme-discoverd(8) nvme-connect(1)
NVME
Part of the nvme-user suite