VM Disk Encryption Keys
In this article, we'll guide you through the process of preparing Vault for storing our LUKS keys and obtaining the necessary details to integrate hosts with Vault. Additionally, we'll aim to conclude by setting up a client to test the entire system. To facilitate this, you should have set up a new VM and added an additional disk to it within a cluster.
Approle
To begin, we'll create a new backend on Vault using Approles instead of the KV store. Approles are particularly useful for machine or service authentication rather than human users.
Normally, we'd require the approle_id
and the secret_id
to obtain a valid token from Vault. However, in our current setup, only the approle and being within the specified CIDR range are necessary. Here's the command used:
vault write auth/approle/role/vaultlocker bound_cidr_list=192.168.0.0/24 token_bound_cidrs=192.168.0.0/24 policies=vaultlocker
This command creates an approle named "vaultlocker" with the associated policy "vaultlocker" (which we'll create shortly) and restricts access to my internal network.
Next, we need to create the policy.
Policy
We need to define a policy for this approle. Here's the policy:
path "/vaultlocker/*" {
capabilities = ["create", "read", "update", "delete", "list"]
}
After creating the policy, rerun the approle creation command.
That should cover the necessary configurations.
Vaultlocker
The script we're utilizing, called Vault Locker, appears to be part of the OpenStack suite. It's a relatively small Python script but seems to function effectively.
Installation
Installation is straightforward; you can install the vaultlocker using pip.
pip install vaultlocker
Additionally, you'll need to create the config directory and file:
mkdir /etc/vaultlocker
touch /etc/vaultlocker/vaultlocker.conf
Vaultlocker.conf
Configuration for vaultlocker is stored in /etc/vaultlocker/vaultlocker.conf. It's a simple file containing three key pieces of information. Here's a sample configuration with the IDs omitted:
[vault]
url = http://vault.xxx.host
approle = qqqqq-wwww-eeee-rrr-ttt-yyyy
secret_id = yyy-ttt-rrr-eee-wwww
backend = /vaultlocker
You can retrieve your approle ID using the following command:
vault read auth/approle/role/vaultlocker/role-id
which will output the approle ID.
[jon@jons-laptop ~]$ vault read auth/approle/role/vaultlocker/role-id
Key Value
--- -----
role_id qqqqq-wwww-eeee-rrr-ttt-yyyy
If you've used the provided command to create the approle, the secret ID isn't necessary.
The backend refers to the path where data is stored.
Run
Let's put our setup to the test.
Firstly, we need to gather some information about the disk we intend to encrypt, ideally its UUID. For testing, here we'll be using /dev/sdb1. You can check in /dev/disk/by-uuid to find the UUID of your disk:
[root@test ~]# ls -lash /dev/disk/by-uuid/
total 0
0 drwxr-xr-x. 2 root root 140 Nov 10 03:53 .
0 drwxr-xr-x. 6 root root 120 Nov 10 03:53 ..
0 lrwxrwxrwx. 1 root root 10 Nov 10 03:53 09a0896e-6e60-47d8-a51c-a538b94db494 -> ../../sda1
0 lrwxrwxrwx. 1 root root 9 Nov 10 03:53 2019-09-11-18-50-31-00 -> ../../sr0
0 lrwxrwxrwx. 1 root root 10 Nov 10 03:53 65242782-090c-44ab-8808-289b5903a6a6 -> ../../sdb1
0 lrwxrwxrwx. 1 root root 10 Nov 10 03:53 e45b5102-c583-4b96-805b-b52a4c440ce4 -> ../../dm-0
0 lrwxrwxrwx. 1 root root 10 Nov 10 03:53 ef376ffc-983c-4cab-859a-2b8d6ba5faf5 -> ../../dm-1
Now that we have the UUID, let's proceed with encrypting it and verifying if the LUKS key is sent to Vault! Run the following command, replacing the UUID and block device with your own:
[root@test ~]# vaultlocker encrypt --uuid 65242782-090c-44ab-8808-289b5903a6a6 /dev/sdb1
You should receive an output similar to this:
DEBUG:urllib3.connectionpool:Starting new HTTP connection (1): vault.haynet.host:80
DEBUG:urllib3.connectionpool:http://vault.haynet.host:80 "POST /v1/auth/approle/login HTTP/1.1" 200 487
INFO:vaultlocker.dmcrypt:LUKS formatting /dev/sdb1 using UUID:65242782-090c-44ab-8808-289b5903a6a6
INFO:vaultlocker.dmcrypt:udevadm trigger block/add for /dev/sdb1
INFO:vaultlocker.dmcrypt:udevadm settle /dev/disk/by-uuid/65242782-090c-44ab-8808-289b5903a6a6
DEBUG:urllib3.connectionpool:http://vault.haynet.host:80 "POST /v1/vaultlocker/test.haynet.host/65242782-090c-44ab-8808-289b5903a6a6 HTTP/1.1" 204 0
DEBUG:urllib3.connectionpool:http://vault.haynet.host:80 "GET /v1/vaultlocker/test.haynet.host/65242782-090c-44ab-8808-289b5903a6a6 HTTP/1.1" 200 864
INFO:vaultlocker.dmcrypt:LUKS opening 65242782-090c-44ab-8808-289b5903a6a6
INFO:root:Enabling systemd unit for [email protected]
Created symlink from /etc/systemd/system/multi-user.target.wants/[email protected] to /usr/local/lib/systemd/system/[email protected].
[root@test ~]#
I've added line breaks for readability. In summary, it worked flawlessly!
It successfully accessed the Vault cluster, formatted the disk, encrypted it, and then extracted the hostname of the machine. Afterward, it created a new secret in the /vaultlocker backend, storing the LUKS key under the disk's UUID.
Let's verify this in the UI:

Now, onto the final step... mounting at boot.
Setting up the service file
Vaultlocker has generated a systemd service file for us. While the current configuration decrypts the device on boot, we also want it to mount. Let's add the mount command to the service file:
[Unit]
Description=vaultlocker retrieve: %i
DefaultDependencies=no
After=networking.service
[Service]
Type=oneshot
KillMode=none
Environment=VAULTLOCKER_TIMEOUT=10000
ExecStart=/bin/sh -c 'vaultlocker --retry $VAULTLOCKER_TIMEOUT decrypt %i && /usr/bin/mount -t ext4 /dev/mapper/crypt-65242782-090c-44ab-8808-289b5903a6a6 /test'
TimeoutSec=0
[Install]
WantedBy=multi-user.target
This addition ensures that the device is mounted to /test after decryption.
With these steps completed, your setup should be ready for use.
Last updated