Bookmark this page

Automating Storage Device Decryption with NBDE

Objectives

  • Manage decryption policy and automatically decrypt storage when specified conditions are met, by using NBDE.

Introducing Network-bound Disk Encryption (NBDE)

In many environments, the default workflow to decrypt devices that are encrypted by using Linux Unified Key Setup (LUKS) is to manually type the password for disk decryption. When a system starts, the password must be entered manually to allow the system to mount the encrypted disk. Typing a passphrase is either not convenient or not possible for large data centers or cloud VM instances. Network-bound Disk Encryption (NBDE) securely automates the decryption of those encrypted disks without manually entering any passphrase at boot time, by ensuring that certain criteria are met. You can use NBDE to automatically decrypt LUKS storage devices that contain root and non-root file systems.

Overview of NBDE Components

The architecture of NBDE uses two key components: the Clevis framework and the Tang server. The Clevis framework is a pluggable framework that supports NBDE on the client side and automates unlocking LUKS-encrypted block devices. The Tang server supports NBDE on the server side, and makes data available on a system when that system can reach the Tang server over a specific secure network. The Clevis framework supports plug-ins, also called pins, to interact with Tang servers. Both the Clevis framework and the Tang server use the JOSE framework as their back end for encryption and decryption.

Figure 3.1: NBDE architecture with Clevis and Tang

Clevis gets a list of the keys for each Tang server, and uses one of those keys to generate an encryption key. The Clevis pin then uses that encryption key to encrypt the data. The encryption generates some state information, which is stored in the LUKS header. That state information is accessible with the luksmeta show command.

Configuring NBDE with System Roles

The RHEL System Roles collection provides Ansible roles and modules to create consistent configurations for RHEL systems.

The rhel-system-roles package contains the nbde_client and nbde_server roles to automate the deployment of NBDE by using Clevis and Tang in one or more servers.

To use the RHEL System Roles, you must install the ansible-core and rhel-system-roles packages on the control node, and you must grant permissions and access to the managed nodes.

Setting up Tang Servers

Use the nbde_server role to deploy and configure Tang servers:

---
- hosts: all

  vars:
    nbde_server_rotate_keys: yes
    nbde_server_manage_firewall: true
    nbde_server_manage_selinux: true

  roles:
    - rhel-system-roles.nbde_server

Setting up the Clevis Client

The nbde_client role configures the Clevis client. This role requires the volumes to be already encrypted with LUKS, and that the role can bind a volume to one or more NBDE servers. You can preserve the existing passphrase or delete it. If you remove the original passphrase, then the volume can be unlocked by using only NBDE. If you provide a passphrase and a key file in the playbook, then the role uses the first entry and ignores all other entries.

You can use a Tang binding to map a device to one or more servers. You can have multiple bindings for the same device. To create or update a binding, set the state variable to the present value. To remove a binding, set the state variable to the absent value.

The following example configures the Clevis client for two devices with two Tang servers:

---
- hosts: all

  vars:
    nbde_client_bindings:
      - device: /dev/rhel/root
        encryption_key_src: /etc/luks/keyfile
        servers:
          - http://server1.example.com
          - http://server2.example.com
      - device: /dev/rhel/swap
        encryption_key_src: /etc/luks/keyfile
        servers:
          - http://server1.example.com
          - http://server2.example.com

  roles:
    - rhel-system-roles.nbde_client

Note

The Clevis client requires networking to be available when mounting Tang bindings. You can use the grubby tool to ensure that networking is available during the early boot process.

[root@host ~]# grubby --update-kernel=ALL --args="rd.neednet=1"

Manual NBDE Configuration

If the RHEL System Role configuration method is not possible, then you can instead manually install and configure NBDE.

Configuring a Tang Server

To begin configuring a Tang server, install the tang package. This package installs the tangd service, which uses systemd socket activation, so it starts with the first connection.

Use the following command to enable socket activation for the tangd service:

[root@host ~]# systemctl enable tangd.socket --now
Created symlink from /etc/systemd/system/multi-user.target.wants/tangd.socket to /usr/lib/systemd/system/tangd.socket.

Note

By default, the tangd service binds to the 80/TCP port. Red Hat Enterprise Linux blocks this port by default.

To stop the tangd service, disable the socket activation for that service as follows:

[root@host ~]# systemctl disable tangd.socket --now
Removed symlink /etc/systemd/system/multi-user.target.wants/tangd.socket.

Note

You can test whether a Tang server is accessible:

[root@host ~]# curl -f http://demotang.lab.example.com/adv

Managing Keys for Tang Servers

Red Hat recommends that you periodically rotate the signature and exchange keys that a Tang server uses. The rotation interval for those keys depends on your application, key sizes, and organizational policies. The Tang server stores the signature and exchange keys in the /var/db/tang directory. To rotate the Tang server keys, rename the existing keys to include a dot as a prefix, and then generate new keys with the jose command for the JOSE framework, as follows:

[root@host ~]# cd /var/db/tang
[root@host tang]# jose jwk gen -i '{"alg":"ES512"}' \
    -o signature.jwk
[root@host tang]# jose jwk gen -i '{"alg":"ECMR"}' \
    o exchange.jwk

Existing client connections use the earlier keys and the Tang server uses the new keys automatically for new client bindings. When all existing client connections finish, you can safely remove the earlier keys.

Note

You must update the clients to use the new keys. To refresh the client keys usage, bind the encrypted device with the tang server again by using the following command:

[root@host ~]# clevis luks bind -d /dev/DEVICE tang '{"url":"http://demotang.lab.example.com"}'

Configuring the Clevis Framework

To configure the Clevis framework with LUKS support, install the clevis, clevis-luks, and clevis-dracut packages. The clevis luks bind command binds a block device to a Tang server. The command also associates a binding policy with the device, which decrypts the device based on the Tang server availability. Available binding policies include the REST HTTP escrow server policy, Shamir's Secret Sharing (SSS) policy, and the Tang binding server policy. The following example binds the /dev/vda1 device to the demotang.lab.example.com Tang server:

[root@host ~]# clevis luks bind -d /dev/vda1 tang '{"url":"http://demotang.lab.example.com"}'

The previous example uses the -d option to specify the device that binds to the Tang server.

The example also associates a binding policy, the Tang binding policy, to bind the device to the Tang server. A Tang binding server policy definition requires the base URL for the Tang server. Other policies are also available, such as the SSS policy.

If the policy requirements are not met, such as if the Tang server is unavailable, then the Clevis framework prompts for the LUKS passphrase during the boot process.

Important

If you are configuring Clevis to decrypt a block device that contains the root file system, then you must re-create the initramfs image with the dracut -f command. For other block devices, you must configure path-based execution by enabling the clevis-luks-askpass.path systemd unit as follows:

[root@host ~]# systemctl enable clevis-luks-askpass.path
Created symlink from /etc/systemd/system/remote-fs.target.wants/clevis-luks-askpass.path to /usr/lib/systemd/system/clevis-luks-askpass.path.

Shamir's Secret Sharing (SSS)

The SSS policy supports the definition of complex policies with multiple Tang servers. You can define a policy with SSS that requires a minimum number of Tang servers to be available before a LUKS-encrypted block device can be decrypted.

The following example binds the /dev/vdb1 device to an SSS policy that defines three Tang servers and requires at least two of them to be available for automatic decryption to occur.

[root@host ~]# cfg=$'{"t":2,"pins":{"tang":[\n
    {"url":"http://demotang1.lab.example.com"},\n
    {"url":"http://demotang2.lab.example.com"},\n
    {"url":"http://demotang3.lab.example.com"}]}}'
[root@host ~]# clevis luks bind -d /dev/vdb1 sss "$cfg"
The advertisement contains the following signing keys:

4R1tkfaTw-67bW0uxTAmTprUPoo

Do you wish to trust these keys? [ynYN] Y
The advertisement contains the following signing keys:

gks_IaVo1yog0KuQei95rg_yGns

Do you wish to trust these keys? [ynYN] Y
The advertisement contains the following signing keys:

vA5xAeUiKPqvkg4UyR4TemzXoAw

Do you wish to trust these keys? [ynYN] Y
You are about to initialize a LUKS device for metadata storage.
Attempting to initialize it may result in data loss if data was
already written into the LUKS header gap in a different format.
A backup is advised before initialization is performed.

Do you wish to initialize /dev/vdb1? [yn] y
Enter existing LUKS password: demopass

For each Tang server, you must trust the key for that server.

Persistently Mounting LUKS File Systems

Edit the /etc/crypttab file to specify the encrypted block devices to open, decrypt, and map at boot time. This file contains an entry for each encrypted block device. Two entries in /etc/crypttab might appear as follows:

decrypted1  /dev/vdb1  none  _netdev
decrypted2  UUID=43d8995e-b876-4385-b124-7e402446d6c7  none  _netdev

The first field contains the name to use for the decrypted block device. This name maps to the corresponding /dev/mapper/name device file. In the example, /dev/mapper/decrypted1 is the name of the first mapped and decrypted block device.

The second field includes either the device name or the LUKS UUID (from the cryptsetup luksUUID <device> command) for the encrypted LUKS device. In this example, the encrypted /dev/vdb1 block device maps to the decrypted /dev/mapper/decrypted1 device mapping. The encrypted block device that is labeled with the 43d8995e-b876-4385-b124-7e402446d6c7 LUKS UUID maps to the decrypted /dev/mapper/decrypted2 device mapping.

The third field specifies the absolute path to a file that contains the encryption password. The field is set to none in the example, which has special meaning. In this case, either the boot process pauses for the manual entry of the encryption password on the machine's console, or the boot process triggers block device decryption with NBDE.

Finally, the last field includes a comma-separated list of options, and in this case specifies only the _netdev option. At boot time, NBDE attempts to unlock all block devices with the _netdev option.

Important

If you are using NBDE Tang Servers to decrypt devices, include the _netdev option in the /dev/fstab file. NBDE uses the network to contact those servers, and so decryption cannot occur until networking is available.

If you are not using NBDE and the device does not need the network to be available to be decrypted, then you can omit the fourth field or use other options such as the discard option.

When the LUKS-encrypted block device maps to the /dev/mapper/name device mapping, you can use the device mapping to mount this device to a specific mount point with the /etc/fstab file.

The following example mounts the file system of the decrypted /dev/mapper/decrypted1 device mapping to the /encrypted directory. This example assumes that the underlying file system on the device is XFS.

...output omitted...
/dev/mapper/decrypted1   /encrypted       xfs    _netdev        1 2

Device Decryption at Boot Time

You can use the /etc/crypttab file alone to configure device decryption at boot time with LUKS. LUKS decrypts the device by prompting you to manually enter passwords into the console at boot time or by storing passwords in plain text on a decrypted device. This way of decryption is inadequate for use cases where servers must boot unattended and still keep the decryption password secure.

NBDE provides a mechanism to automatically decrypt LUKS devices at boot time securely. This mechanism is based on two key components:

  • The Clevis client, which runs on the system, decrypts devices, and defines the policy whose conditions must be met for the data to be decrypted.

  • The Tang server, which Clevis clients contact to determine whether they are booting with access to a secure network and therefore decrypt their LUKS devices.

By using NBDE, you can prevent automatic decryption of a device that is removed from the data center.

References

clevis-encrypt-tang(1), clevis-encrypt-sss(1), and the jose-jwk-gen(1) man pages

For more information, refer to the Network-bound Disk Encryption chapter in the Red Hat Enterprise Linux 9 Security Hardening Guide at https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/9/html/security_hardening/configuring-automated-unlocking-of-encrypted-volumes-using-policy-based-decryption_security-hardening#network-bound-disk-encryption_configuring-automated-unlocking-of-encrypted-volumes-using-policy-based-decryption

Revision: rh415-9.2-a821299