This commit sets the foundation for encrypting the libvirt secrets by providing a secure way to pass a secret encryption key to the virtsecretd service.
A random secret key is generated using the new virt-secret-init-encryption service. This key can be consumed by the virtsecretd service. By using the "Before=" directive in the new secret-init-encryption service and using "Requires=" directive in the virtsecretd service, we make sure that the daemon is run only after we have an encrypted secret key file generated and placed in /var/lib/libvirt/secrets. The virtsecretd service can then read the key from CREDENTIALS_DIRECTORY. [1] This setup therefore provides a default key out-of-the-box for initial use. A subsequent commit will introduce the logic for virtsecretd to access and use this key via the $CREDENTIALS_DIRECTORY environment variable. [2] [1] https://www.freedesktop.org/software/systemd/man/latest/systemd-creds.html [2] https://systemd.io/CREDENTIALS/ Signed-off-by: Arun Menon <[email protected]> --- libvirt.spec.in | 4 ++++ src/meson.build | 1 + src/secret/meson.build | 24 ++++++++++++++++++++++++ src/secret/secret-init-encryption.in | 10 ++++++++++ src/secret/virtsecretd.service.extra.in | 8 ++++++++ 5 files changed, 47 insertions(+) create mode 100644 src/secret/secret-init-encryption.in diff --git a/libvirt.spec.in b/libvirt.spec.in index 62af7fb517..dba8a71311 100644 --- a/libvirt.spec.in +++ b/libvirt.spec.in @@ -1880,13 +1880,16 @@ exit 0 %pre daemon-driver-secret %libvirt_sysconfig_pre virtsecretd %libvirt_systemd_unix_pre virtsecretd +%libvirt_systemd_oneshot_pre virt-secret-init-encryption %posttrans daemon-driver-secret %libvirt_sysconfig_posttrans virtsecretd %libvirt_systemd_unix_posttrans virtsecretd +%libvirt_systemd_unix_posttrans virt-secret-init-encryption %preun daemon-driver-secret %libvirt_systemd_unix_preun virtsecretd +%libvirt_systemd_unix_preun virt-secret-init-encryption %pre daemon-driver-storage-core %libvirt_sysconfig_pre virtstoraged @@ -2238,6 +2241,7 @@ exit 0 %{_datadir}/augeas/lenses/virtsecretd.aug %{_datadir}/augeas/lenses/tests/test_virtsecretd.aug %{_unitdir}/virtsecretd.service +%{_unitdir}/virt-secret-init-encryption.service %{_unitdir}/virtsecretd.socket %{_unitdir}/virtsecretd-ro.socket %{_unitdir}/virtsecretd-admin.socket diff --git a/src/meson.build b/src/meson.build index 47c978cc1f..f18f562fd9 100644 --- a/src/meson.build +++ b/src/meson.build @@ -837,6 +837,7 @@ if conf.has('WITH_LIBVIRTD') 'sbindir': sbindir, 'sysconfdir': sysconfdir, 'initconfdir': initconfdir, + 'localstatedir': localstatedir, 'name': unit['name'], 'service': unit['service'], 'SERVICE': unit['service'].to_upper(), diff --git a/src/secret/meson.build b/src/secret/meson.build index 3b859ea7b4..c02d1064a9 100644 --- a/src/secret/meson.build +++ b/src/secret/meson.build @@ -31,6 +31,30 @@ if conf.has('WITH_SECRETS') 'name': 'virtsecretd', } + secret_init_encryption_unit = { + 'service': 'virt-secret-init-encryption', + 'name': 'Libvirt Secret Encryption Init', + 'input': 'secret-init-encryption.in', + } + + unit_conf = configuration_data() + unit_conf.set('runstatedir', runstatedir) + unit_conf.set('sbindir', sbindir) + unit_conf.set('localstatedir', localstatedir) + unit_conf.set('sysconfdir', sysconfdir) + unit_conf.set('initconfdir', initconfdir) + unit_conf.set('name', secret_init_encryption_unit['name']) + unit_conf.set('service', secret_init_encryption_unit['service']) + unit_conf.set('SERVICE', secret_init_encryption_unit['service'].to_upper()) + + configure_file( + input: secret_init_encryption_unit['input'], + output: '@[email protected]'.format(secret_init_encryption_unit['service']), + configuration: unit_conf, + install: true, + install_dir: unitdir, + ) + virt_daemon_units += { 'service': 'virtsecretd', 'name': 'secret', diff --git a/src/secret/secret-init-encryption.in b/src/secret/secret-init-encryption.in new file mode 100644 index 0000000000..29da6dbcce --- /dev/null +++ b/src/secret/secret-init-encryption.in @@ -0,0 +1,10 @@ +[Unit] +Before=virtsecretd.service +ConditionPathExists=!@localstatedir@/lib/libvirt/secrets/secrets-encryption-key + +[Service] +Type=oneshot +ExecStart=/usr/bin/sh -c 'umask 0066 && (dd if=/dev/urandom status=none bs=32 count=1 | systemd-creds encrypt --name=secrets-encryption-key - @localstatedir@/lib/libvirt/secrets/secrets-encryption-key)' + +[Install] +WantedBy=multi-user.target diff --git a/src/secret/virtsecretd.service.extra.in b/src/secret/virtsecretd.service.extra.in index 1fc8c672f7..116458b22a 100644 --- a/src/secret/virtsecretd.service.extra.in +++ b/src/secret/virtsecretd.service.extra.in @@ -1,2 +1,10 @@ # The contents of this unit will be merged into a base template. # Additional units might be merged as well. See meson.build for details. +# +[Unit] +Requires=virt-secret-init-encryption.service +After=virt-secret-init-encryption.service + +[Service] +LoadCredentialEncrypted=secrets-encryption-key:@localstatedir@/lib/libvirt/secrets/secrets-encryption-key +Environment=SECRETS_ENCRYPTION_KEY=%d/secrets-encryption-key -- 2.51.1
