mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-30 16:35:24 +00:00
qemu: add support for librbd layered encryption
This commit enables libvirt users to use layered encryption of RBD images, using the librbd encryption engine. This allows opening of an encrypted cloned image whose parent is encrypted with a possibly different encryption key. To open such images, multiple encryption secrets are expected to be defined under the encryption XML tag. Signed-off-by: Or Ozeri <oro@il.ibm.com> Reviewed-by: Peter Krempa <pkrempa@redhat.com>
This commit is contained in:
parent
1992ae40fa
commit
77c9663d72
@ -28,7 +28,10 @@ network disks. If the engine tag is not specified, the ``qemu`` engine will be
|
||||
used by default (assuming the qemu driver is used). Note that ``librbd`` engine
|
||||
is currently only supported by the qemu VM driver, and is not supported by the
|
||||
storage driver. Furthermore, the storage driver currently ignores the ``engine``
|
||||
tag.
|
||||
tag. :since:`since 9.3.0` RBD layered encryption is supported. Layered
|
||||
encryption requires a secret per each encrypted layer. The first secret
|
||||
corresponds to the (child) image itself, the second secret to the parent image,
|
||||
and so forth.
|
||||
|
||||
The ``encryption`` tag can currently contain a sequence of ``secret`` tags, each
|
||||
with mandatory attributes ``type`` and either ``uuid`` or ``usage`` (
|
||||
@ -55,7 +58,8 @@ added to libvirt.
|
||||
The ``luks`` format is specific to a luks encrypted volume and the secret is
|
||||
used in order to either encrypt during volume creation or decrypt the volume for
|
||||
usage by the domain. A single ``<secret type='passphrase'...>`` element is
|
||||
expected. :since:`Since 2.1.0` .
|
||||
expected (except for the case of RBD layered encryption mentioned above).
|
||||
:since:`Since 2.1.0` .
|
||||
|
||||
For volume creation, it is possible to specify the encryption algorithm used to
|
||||
encrypt the luks volume. The following two optional elements may be provided for
|
||||
@ -102,7 +106,8 @@ can only be applied to RBD network disks (RBD images). Since the ``librbd``
|
||||
engine is currently not supported by the libvirt storage driver, you cannot use
|
||||
it to control such disks. However, pre-formatted RBD luks2 disks can be loaded
|
||||
to a qemu VM using the qemu VM driver. A single
|
||||
``<secret type='passphrase'...>`` element is expected.
|
||||
``<secret type='passphrase'...>`` element is expected (except for the case of
|
||||
RBD layered encryption mentioned above).
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
@ -26,7 +26,9 @@
|
||||
</optional>
|
||||
<optional>
|
||||
<interleave>
|
||||
<ref name="secret"/>
|
||||
<oneOrMore>
|
||||
<ref name="secret"/>
|
||||
</oneOrMore>
|
||||
<optional>
|
||||
<interleave>
|
||||
<element name="cipher">
|
||||
|
@ -564,6 +564,8 @@ qemuBlockStorageSourceGetRBDProps(virStorageSource *src,
|
||||
|
||||
if (src->encryption &&
|
||||
src->encryption->engine == VIR_STORAGE_ENCRYPTION_ENGINE_LIBRBD) {
|
||||
size_t i;
|
||||
|
||||
switch ((virStorageEncryptionFormatType) src->encryption->format) {
|
||||
case VIR_STORAGE_ENCRYPTION_FORMAT_LUKS:
|
||||
encformat = "luks";
|
||||
@ -580,11 +582,19 @@ qemuBlockStorageSourceGetRBDProps(virStorageSource *src,
|
||||
break;
|
||||
}
|
||||
|
||||
if (virJSONValueObjectAdd(&encrypt,
|
||||
"s:format", encformat,
|
||||
"s:key-secret", srcPriv->encinfo[0]->alias,
|
||||
NULL) < 0)
|
||||
return NULL;
|
||||
for (i = src->encryption->nsecrets; i > 0; --i) {
|
||||
g_autoptr(virJSONValue) new = NULL;
|
||||
|
||||
/* we consume the lower layer 'encrypt' into a new object */
|
||||
if (virJSONValueObjectAdd(&new,
|
||||
"s:format", encformat,
|
||||
"s:key-secret", srcPriv->encinfo[i-1]->alias,
|
||||
"A:parent", &encrypt,
|
||||
NULL) < 0)
|
||||
return NULL;
|
||||
|
||||
encrypt = g_steal_pointer(&new);
|
||||
}
|
||||
}
|
||||
|
||||
if (virJSONValueObjectAdd(&ret,
|
||||
|
@ -5198,6 +5198,12 @@ qemuDomainValidateStorageSource(virStorageSource *src,
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (src->encryption->nsecrets > 1) {
|
||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||
_("qemu encryption engine expects only a single secret"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case VIR_STORAGE_ENCRYPTION_ENGINE_LIBRBD:
|
||||
@ -5213,6 +5219,14 @@ qemuDomainValidateStorageSource(virStorageSource *src,
|
||||
_("librbd encryption is supported only with RBD backed disks"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (src->encryption->nsecrets > 1) {
|
||||
if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_RBD_ENCRYPTION_LAYERING)) {
|
||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||
_("librbd encryption layering is not supported by this QEMU binary"));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case VIR_STORAGE_ENCRYPTION_ENGINE_DEFAULT:
|
||||
|
@ -3346,6 +3346,14 @@ qemuValidateDomainDeviceDefDisk(const virDomainDiskDef *disk,
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (disk->bus == VIR_DOMAIN_DISK_BUS_SD &&
|
||||
disk->src && disk->src->encryption && disk->src->encryption->nsecrets > 1) {
|
||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
||||
_("sd card '%s' does not support multiple encryption secrets"),
|
||||
disk->dst);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (disk->src->type == VIR_STORAGE_TYPE_VHOST_USER) {
|
||||
if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VHOST_USER_BLK)) {
|
||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||
|
@ -0,0 +1 @@
|
||||
unsupported configuration: librbd encryption layering is not supported by this QEMU binary
|
@ -0,0 +1,39 @@
|
||||
LC_ALL=C \
|
||||
PATH=/bin \
|
||||
HOME=/var/lib/libvirt/qemu/domain--1-encryptdisk \
|
||||
USER=test \
|
||||
LOGNAME=test \
|
||||
XDG_DATA_HOME=/var/lib/libvirt/qemu/domain--1-encryptdisk/.local/share \
|
||||
XDG_CACHE_HOME=/var/lib/libvirt/qemu/domain--1-encryptdisk/.cache \
|
||||
XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-encryptdisk/.config \
|
||||
/usr/bin/qemu-system-x86_64 \
|
||||
-name guest=encryptdisk,debug-threads=on \
|
||||
-S \
|
||||
-object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/lib/libvirt/qemu/domain--1-encryptdisk/master-key.aes"}' \
|
||||
-machine pc-i440fx-2.1,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=off \
|
||||
-accel tcg \
|
||||
-cpu qemu64 \
|
||||
-m 1024 \
|
||||
-object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":1073741824}' \
|
||||
-overcommit mem-lock=off \
|
||||
-smp 1,sockets=1,cores=1,threads=1 \
|
||||
-uuid 496898a6-e6ff-f7c8-5dc2-3cf410945ee9 \
|
||||
-display none \
|
||||
-no-user-config \
|
||||
-nodefaults \
|
||||
-chardev socket,id=charmonitor,fd=1729,server=on,wait=off \
|
||||
-mon chardev=charmonitor,id=monitor,mode=control \
|
||||
-rtc base=utc \
|
||||
-no-shutdown \
|
||||
-boot strict=on \
|
||||
-device '{"driver":"piix3-usb-uhci","id":"usb","bus":"pci.0","addr":"0x1.0x2"}' \
|
||||
-object '{"qom-type":"secret","id":"libvirt-1-format-encryption-secret0","data":"9eao5F8qtkGt+seB1HYivWIxbtwUu6MQtg1zpj/oDtUsPr1q8wBYM91uEHCn6j/1","keyid":"masterKey0","iv":"AAECAwQFBgcICQoLDA0ODw==","format":"base64"}' \
|
||||
-object '{"qom-type":"secret","id":"libvirt-1-format-encryption-secret1","data":"9eao5F8qtkGt+seB1HYivWIxbtwUu6MQtg1zpj/oDtUsPr1q8wBYM91uEHCn6j/1","keyid":"masterKey0","iv":"AAECAwQFBgcICQoLDA0ODw==","format":"base64"}' \
|
||||
-object '{"qom-type":"secret","id":"libvirt-1-format-encryption-secret2","data":"9eao5F8qtkGt+seB1HYivWIxbtwUu6MQtg1zpj/oDtUsPr1q8wBYM91uEHCn6j/1","keyid":"masterKey0","iv":"AAECAwQFBgcICQoLDA0ODw==","format":"base64"}' \
|
||||
-blockdev '{"driver":"rbd","pool":"pool","image":"image","server":[{"host":"mon1.example.org","port":"6321"},{"host":"mon2.example.org","port":"6322"},{"host":"mon3.example.org","port":"6322"}],"encrypt":{"format":"luks","key-secret":"libvirt-1-format-encryption-secret0","parent":{"format":"luks","key-secret":"libvirt-1-format-encryption-secret1","parent":{"format":"luks","key-secret":"libvirt-1-format-encryption-secret2"}}},"node-name":"libvirt-1-storage","auto-read-only":true,"discard":"unmap"}' \
|
||||
-blockdev '{"node-name":"libvirt-1-format","read-only":false,"driver":"raw","file":"libvirt-1-storage"}' \
|
||||
-device '{"driver":"virtio-blk-pci","bus":"pci.0","addr":"0x2","drive":"libvirt-1-format","id":"virtio-disk0","bootindex":1}' \
|
||||
-audiodev '{"id":"audio1","driver":"none"}' \
|
||||
-device '{"driver":"virtio-balloon-pci","id":"balloon0","bus":"pci.0","addr":"0x3"}' \
|
||||
-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \
|
||||
-msg timestamp=on
|
@ -0,0 +1,41 @@
|
||||
<domain type='qemu'>
|
||||
<name>encryptdisk</name>
|
||||
<uuid>496898a6-e6ff-f7c8-5dc2-3cf410945ee9</uuid>
|
||||
<memory unit='KiB'>1048576</memory>
|
||||
<currentMemory unit='KiB'>524288</currentMemory>
|
||||
<vcpu placement='static'>1</vcpu>
|
||||
<os>
|
||||
<type arch='x86_64' machine='pc-i440fx-2.1'>hvm</type>
|
||||
<boot dev='hd'/>
|
||||
</os>
|
||||
<clock offset='utc'/>
|
||||
<on_poweroff>destroy</on_poweroff>
|
||||
<on_reboot>restart</on_reboot>
|
||||
<on_crash>destroy</on_crash>
|
||||
<devices>
|
||||
<emulator>/usr/bin/qemu-system-x86_64</emulator>
|
||||
<disk type='network' device='disk'>
|
||||
<driver name='qemu' type='raw'/>
|
||||
<source protocol='rbd' name='pool/image'>
|
||||
<host name='mon1.example.org' port='6321'/>
|
||||
<host name='mon2.example.org' port='6322'/>
|
||||
<host name='mon3.example.org' port='6322'/>
|
||||
<encryption format='luks' engine='librbd'>
|
||||
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccc2f80fb0'/>
|
||||
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccc2f80d6f'/>
|
||||
<secret type='passphrase' uuid='f52a81b2-424e-490c-823d-6bd4235bc572'/>
|
||||
</encryption>
|
||||
</source>
|
||||
<target dev='vda' bus='virtio'/>
|
||||
</disk>
|
||||
<controller type='usb' index='0'>
|
||||
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
|
||||
</controller>
|
||||
<controller type='pci' index='0' model='pci-root'/>
|
||||
<input type='mouse' bus='ps2'/>
|
||||
<input type='keyboard' bus='ps2'/>
|
||||
<memballoon model='virtio'>
|
||||
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
|
||||
</memballoon>
|
||||
</devices>
|
||||
</domain>
|
@ -1249,6 +1249,8 @@ mymain(void)
|
||||
DO_TEST_CAPS_LATEST("disk-network-rbd");
|
||||
DO_TEST_CAPS_VER_PARSE_ERROR("disk-network-rbd-encryption", "6.0.0");
|
||||
DO_TEST_CAPS_LATEST("disk-network-rbd-encryption");
|
||||
DO_TEST_CAPS_VER_PARSE_ERROR("disk-network-rbd-encryption-layering", "7.2.0");
|
||||
DO_TEST_CAPS_LATEST("disk-network-rbd-encryption-layering");
|
||||
DO_TEST_CAPS_LATEST_PARSE_ERROR("disk-encryption-wrong");
|
||||
DO_TEST_CAPS_LATEST("disk-network-rbd-no-colon");
|
||||
/* qemu-6.0 is the last qemu version supporting sheepdog */
|
||||
|
@ -0,0 +1,46 @@
|
||||
<domain type='qemu'>
|
||||
<name>encryptdisk</name>
|
||||
<uuid>496898a6-e6ff-f7c8-5dc2-3cf410945ee9</uuid>
|
||||
<memory unit='KiB'>1048576</memory>
|
||||
<currentMemory unit='KiB'>524288</currentMemory>
|
||||
<vcpu placement='static'>1</vcpu>
|
||||
<os>
|
||||
<type arch='x86_64' machine='pc-i440fx-2.1'>hvm</type>
|
||||
<boot dev='hd'/>
|
||||
</os>
|
||||
<cpu mode='custom' match='exact' check='none'>
|
||||
<model fallback='forbid'>qemu64</model>
|
||||
</cpu>
|
||||
<clock offset='utc'/>
|
||||
<on_poweroff>destroy</on_poweroff>
|
||||
<on_reboot>restart</on_reboot>
|
||||
<on_crash>destroy</on_crash>
|
||||
<devices>
|
||||
<emulator>/usr/bin/qemu-system-x86_64</emulator>
|
||||
<disk type='network' device='disk'>
|
||||
<driver name='qemu' type='raw'/>
|
||||
<source protocol='rbd' name='pool/image'>
|
||||
<host name='mon1.example.org' port='6321'/>
|
||||
<host name='mon2.example.org' port='6322'/>
|
||||
<host name='mon3.example.org' port='6322'/>
|
||||
<encryption format='luks' engine='librbd'>
|
||||
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccc2f80fb0'/>
|
||||
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccc2f80d6f'/>
|
||||
<secret type='passphrase' uuid='f52a81b2-424e-490c-823d-6bd4235bc572'/>
|
||||
</encryption>
|
||||
</source>
|
||||
<target dev='vda' bus='virtio'/>
|
||||
<address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
|
||||
</disk>
|
||||
<controller type='usb' index='0' model='piix3-uhci'>
|
||||
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
|
||||
</controller>
|
||||
<controller type='pci' index='0' model='pci-root'/>
|
||||
<input type='mouse' bus='ps2'/>
|
||||
<input type='keyboard' bus='ps2'/>
|
||||
<audio id='1' type='none'/>
|
||||
<memballoon model='virtio'>
|
||||
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
|
||||
</memballoon>
|
||||
</devices>
|
||||
</domain>
|
@ -325,6 +325,7 @@ mymain(void)
|
||||
DO_TEST_NOCAPS("disk-network-gluster");
|
||||
DO_TEST_NOCAPS("disk-network-rbd");
|
||||
DO_TEST_CAPS_LATEST("disk-network-rbd-encryption");
|
||||
DO_TEST_CAPS_LATEST("disk-network-rbd-encryption-layering");
|
||||
DO_TEST_NOCAPS("disk-network-source-auth");
|
||||
DO_TEST_NOCAPS("disk-network-sheepdog");
|
||||
DO_TEST_NOCAPS("disk-network-vxhs");
|
||||
|
Loading…
x
Reference in New Issue
Block a user