[PATCH v5 0/5] Add support for librbd encryption

v5: rebased + nit fixes suggested by Peter v4: - added disk post parse to image creation flow in qemublocktest (since more tests failed after adding engine validation) - removed symlink changes - added luks2 and engine documentation - switched to using enum engine instead of int - added validation for encryption engine and formats v3: rebased on master v2: addressed (hopefully) all of Peter's v1 comments (thanks Peter!) Feel free to make any other changes before pushing. Thanks! Or Ozeri (5): qemu: add disk post parse to qemublocktest qemu: capablities: Detect presence of 'rbd-encryption' as QEMU_CAPS_RBD_ENCRYPTION conf: add encryption engine property qemu: add librbd encryption engine conf: add luks2 encryption format docs/formatstorageencryption.html.in | 29 ++++++- docs/schemas/domainbackup.rng | 7 ++ docs/schemas/storagecommon.rng | 9 ++ src/conf/storage_encryption_conf.c | 28 ++++++- src/conf/storage_encryption_conf.h | 11 +++ src/qemu/qemu_block.c | 41 +++++++++ src/qemu/qemu_capabilities.c | 2 + src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_domain.c | 69 ++++++++++++++- src/qemu/qemu_domain.h | 3 + tests/qemublocktest.c | 29 +++---- .../caps_6.1.0.x86_64.xml | 1 + .../caps_6.2.0.x86_64.xml | 1 + tests/qemustatusxml2xmldata/upgrade-out.xml | 6 +- ...sk-network-rbd-encryption.x86_64-6.0.0.err | 1 + ...-network-rbd-encryption.x86_64-latest.args | 49 +++++++++++ .../disk-network-rbd-encryption.xml | 75 +++++++++++++++++ tests/qemuxml2argvdata/disk-nvme.xml | 2 +- .../qemuxml2argvdata/encrypted-disk-usage.xml | 2 +- tests/qemuxml2argvdata/luks-disks.xml | 4 +- tests/qemuxml2argvdata/user-aliases.xml | 2 +- tests/qemuxml2argvtest.c | 2 + ...k-network-rbd-encryption.x86_64-latest.xml | 83 +++++++++++++++++++ .../disk-slices.x86_64-latest.xml | 4 +- tests/qemuxml2xmloutdata/encrypted-disk.xml | 2 +- .../luks-disks-source-qcow2.x86_64-latest.xml | 14 ++-- .../qemuxml2xmloutdata/luks-disks-source.xml | 10 +-- tests/qemuxml2xmltest.c | 1 + 28 files changed, 443 insertions(+), 45 deletions(-) create mode 100644 tests/qemuxml2argvdata/disk-network-rbd-encryption.x86_64-6.0.0.err create mode 100644 tests/qemuxml2argvdata/disk-network-rbd-encryption.x86_64-latest.args create mode 100644 tests/qemuxml2argvdata/disk-network-rbd-encryption.xml create mode 100644 tests/qemuxml2xmloutdata/disk-network-rbd-encryption.x86_64-latest.xml -- 2.25.1

The post parse callback is part of the real (non-test) processing flow. This commit adds it (for disks) to the qemublocktest flow as well. Specifically, this will be needed for tests that use luks encryption, so that the default encryption engine (which is added in an upcoming commit) will be overridden by qemu. Signed-off-by: Or Ozeri <oro@il.ibm.com> --- src/qemu/qemu_domain.c | 2 +- src/qemu/qemu_domain.h | 3 +++ tests/qemublocktest.c | 29 ++++++++++++----------------- 3 files changed, 16 insertions(+), 18 deletions(-) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 1bd3730281..5ff602e3af 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -5218,7 +5218,7 @@ qemuDomainDeviceDiskDefPostParseRestoreSecAlias(virDomainDiskDef *disk, } -static int +int qemuDomainDeviceDiskDefPostParse(virDomainDiskDef *disk, unsigned int parseFlags) { diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index 9cf5d5479e..6728ab047e 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -857,6 +857,9 @@ int qemuDomainSecretPrepare(virQEMUDriver *driver, int qemuDomainDeviceDefValidateDisk(const virDomainDiskDef *disk, virQEMUCaps *qemuCaps); +int qemuDomainDeviceDiskDefPostParse(virDomainDiskDef *disk, + unsigned int parseFlags); + int qemuDomainPrepareChannel(virDomainChrDef *chr, const char *domainChannelTargetDir) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); diff --git a/tests/qemublocktest.c b/tests/qemublocktest.c index 3e61e923a9..0176fbd3f4 100644 --- a/tests/qemublocktest.c +++ b/tests/qemublocktest.c @@ -276,6 +276,9 @@ testQemuDiskXMLToProps(const void *opaque) VIR_DOMAIN_DEF_PARSE_STATUS))) return -1; + if (qemuDomainDeviceDiskDefPostParse(disk, 0) < 0) + return -1; + if (!(vmdef = virDomainDefNew(data->driver->xmlopt))) return -1; @@ -470,32 +473,24 @@ testQemuImageCreateLoadDiskXML(const char *name, virDomainXMLOption *xmlopt) { - virDomainSnapshotDiskDef *diskdef = NULL; - g_autoptr(xmlDoc) doc = NULL; - g_autoptr(xmlXPathContext) ctxt = NULL; - xmlNodePtr node; + virDomainDiskDef *disk = NULL; g_autofree char *xmlpath = NULL; - virStorageSource *ret = NULL; + g_autofree char *xmlstr = NULL; xmlpath = g_strdup_printf("%s%s.xml", testQemuImageCreatePath, name); - if (!(doc = virXMLParseFileCtxt(xmlpath, &ctxt))) + if (virTestLoadFile(xmlpath, &xmlstr) < 0) return NULL; - if (!(node = virXPathNode("//disk", ctxt))) { - VIR_TEST_VERBOSE("failed to find <source> element\n"); + /* qemu stores node names in the status XML portion */ + if (!(disk = virDomainDiskDefParse(xmlstr, xmlopt, + VIR_DOMAIN_DEF_PARSE_STATUS))) return NULL; - } - diskdef = g_new0(virDomainSnapshotDiskDef, 1); - - if (virDomainSnapshotDiskDefParseXML(node, ctxt, diskdef, - VIR_DOMAIN_DEF_PARSE_STATUS, - xmlopt) == 0) - ret = g_steal_pointer(&diskdef->src); + if (qemuDomainDeviceDiskDefPostParse(disk, 0) < 0) + return NULL; - virDomainSnapshotDiskDefFree(diskdef); - return ret; + return disk->src; } -- 2.25.1

rbd encryption is new in qemu 6.1.0. This commit adds capability probing for it. Signed-off-by: Or Ozeri <oro@il.ibm.com> --- src/qemu/qemu_capabilities.c | 2 ++ src/qemu/qemu_capabilities.h | 1 + tests/qemucapabilitiesdata/caps_6.1.0.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_6.2.0.x86_64.xml | 1 + 4 files changed, 5 insertions(+) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index cddd39924d..6e72a18455 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -651,6 +651,7 @@ VIR_ENUM_IMPL(virQEMUCaps, "chardev.json", /* QEMU_CAPS_CHARDEV_JSON */ "device.json", /* QEMU_CAPS_DEVICE_JSON */ "query-dirty-rate", /* QEMU_CAPS_QUERY_DIRTY_RATE */ + "rbd-encryption", /* QEMU_CAPS_RBD_ENCRYPTION */ ); @@ -1561,6 +1562,7 @@ static struct virQEMUCapsStringFlags virQEMUCapsQMPSchemaQueries[] = { { "blockdev-add/arg-type/+file/$dynamic-auto-read-only", QEMU_CAPS_BLOCK_FILE_AUTO_READONLY_DYNAMIC }, { "blockdev-add/arg-type/+nvme", QEMU_CAPS_DRIVE_NVME }, { "blockdev-add/arg-type/+file/aio/^io_uring", QEMU_CAPS_AIO_IO_URING }, + { "blockdev-add/arg-type/+rbd/encrypt", QEMU_CAPS_RBD_ENCRYPTION }, { "blockdev-add/arg-type/discard", QEMU_CAPS_DRIVE_DISCARD }, { "blockdev-add/arg-type/detect-zeroes", QEMU_CAPS_DRIVE_DETECT_ZEROES }, { "blockdev-backup", QEMU_CAPS_BLOCKDEV_BACKUP }, diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index bb53d9ae46..338470ac5d 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -631,6 +631,7 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */ QEMU_CAPS_CHARDEV_JSON, /* -chardev accepts JSON */ QEMU_CAPS_DEVICE_JSON, /* -device accepts JSON */ QEMU_CAPS_QUERY_DIRTY_RATE, /* accepts query-dirty-rate */ + QEMU_CAPS_RBD_ENCRYPTION, /* Ceph RBD encryption support */ QEMU_CAPS_LAST /* this must always be the last item */ } virQEMUCapsFlags; diff --git a/tests/qemucapabilitiesdata/caps_6.1.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_6.1.0.x86_64.xml index 98c2fcedce..e60ed4705b 100644 --- a/tests/qemucapabilitiesdata/caps_6.1.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_6.1.0.x86_64.xml @@ -240,6 +240,7 @@ <flag name='piix4.acpi-root-pci-hotplug'/> <flag name='ich9.acpi-hotplug-bridge'/> <flag name='query-dirty-rate'/> + <flag name='rbd-encryption'/> <version>6001000</version> <kvmVersion>0</kvmVersion> <microcodeVersion>43100243</microcodeVersion> diff --git a/tests/qemucapabilitiesdata/caps_6.2.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_6.2.0.x86_64.xml index 5a46da0a6a..5622745347 100644 --- a/tests/qemucapabilitiesdata/caps_6.2.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_6.2.0.x86_64.xml @@ -241,6 +241,7 @@ <flag name='ich9.acpi-hotplug-bridge'/> <flag name='device.json'/> <flag name='query-dirty-rate'/> + <flag name='rbd-encryption'/> <version>6001050</version> <kvmVersion>0</kvmVersion> <microcodeVersion>43100244</microcodeVersion> -- 2.25.1

This commit extends libvirt XML configuration to support a custom encryption engine. This means that <encryption format="luks" engine="qemu"> becomes valid. The only engine for now is qemu. However, a new engine (librbd) will be added in an upcoming commit. If no engine is specified, qemu will be used (assuming qemu driver is used). Signed-off-by: Or Ozeri <oro@il.ibm.com> --- docs/formatstorageencryption.html.in | 6 +++++ docs/schemas/domainbackup.rng | 7 +++++ docs/schemas/storagecommon.rng | 7 +++++ src/conf/storage_encryption_conf.c | 26 ++++++++++++++++++- src/conf/storage_encryption_conf.h | 9 +++++++ src/qemu/qemu_block.c | 2 ++ src/qemu/qemu_domain.c | 20 ++++++++++++++ tests/qemustatusxml2xmldata/upgrade-out.xml | 6 ++--- tests/qemuxml2argvdata/disk-nvme.xml | 2 +- .../qemuxml2argvdata/encrypted-disk-usage.xml | 2 +- tests/qemuxml2argvdata/luks-disks.xml | 4 +-- tests/qemuxml2argvdata/user-aliases.xml | 2 +- .../disk-slices.x86_64-latest.xml | 4 +-- tests/qemuxml2xmloutdata/encrypted-disk.xml | 2 +- .../luks-disks-source-qcow2.x86_64-latest.xml | 14 +++++----- .../qemuxml2xmloutdata/luks-disks-source.xml | 10 +++---- 16 files changed, 99 insertions(+), 24 deletions(-) diff --git a/docs/formatstorageencryption.html.in b/docs/formatstorageencryption.html.in index 7215c307d7..178fcd0d7c 100644 --- a/docs/formatstorageencryption.html.in +++ b/docs/formatstorageencryption.html.in @@ -23,6 +23,12 @@ content of the <code>encryption</code> tag. Other format values may be defined in the future. </p> + <p> + The <code>encryption</code> tag supports an optional <code>engine</code> + tag, which allows selecting which component actually handles + the encryption. Currently defined values of <code>engine</code> are + <code>qemu</code>. + </p> <p> The <code>encryption</code> tag can currently contain a sequence of <code>secret</code> tags, each with mandatory attributes <code>type</code> diff --git a/docs/schemas/domainbackup.rng b/docs/schemas/domainbackup.rng index c03455a5a7..05cc28ab00 100644 --- a/docs/schemas/domainbackup.rng +++ b/docs/schemas/domainbackup.rng @@ -14,6 +14,13 @@ <value>luks</value> </choice> </attribute> + <optional> + <attribute name="engine"> + <choice> + <value>qemu</value> + </choice> + </attribute> + </optional> <interleave> <ref name="secret"/> <optional> diff --git a/docs/schemas/storagecommon.rng b/docs/schemas/storagecommon.rng index 9ebb27700d..60dcfac06c 100644 --- a/docs/schemas/storagecommon.rng +++ b/docs/schemas/storagecommon.rng @@ -15,6 +15,13 @@ <value>luks</value> </choice> </attribute> + <optional> + <attribute name="engine"> + <choice> + <value>qemu</value> + </choice> + </attribute> + </optional> <interleave> <ref name="secret"/> <optional> diff --git a/src/conf/storage_encryption_conf.c b/src/conf/storage_encryption_conf.c index 9112b96cc7..7fd601e4a2 100644 --- a/src/conf/storage_encryption_conf.c +++ b/src/conf/storage_encryption_conf.c @@ -47,6 +47,11 @@ VIR_ENUM_IMPL(virStorageEncryptionFormat, "default", "qcow", "luks", ); +VIR_ENUM_IMPL(virStorageEncryptionEngine, + VIR_STORAGE_ENCRYPTION_ENGINE_LAST, + "default", "qemu", +); + static void virStorageEncryptionInfoDefClear(virStorageEncryptionInfoDef *def) { @@ -120,6 +125,7 @@ virStorageEncryptionCopy(const virStorageEncryption *src) ret->secrets = g_new0(virStorageEncryptionSecret *, src->nsecrets); ret->nsecrets = src->nsecrets; ret->format = src->format; + ret->engine = src->engine; for (i = 0; i < src->nsecrets; i++) { if (!(ret->secrets[i] = virStorageEncryptionSecretCopy(src->secrets[i]))) @@ -239,6 +245,12 @@ virStorageEncryptionParseNode(xmlNodePtr node, goto cleanup; } + if (virXMLPropEnum(node, "engine", + virStorageEncryptionEngineTypeFromString, + VIR_XML_PROP_NONZERO, + &encdef->engine) < 0) + goto cleanup; + if ((n = virXPathNodeSet("./secret", ctxt, &nodes)) < 0) goto cleanup; @@ -327,6 +339,7 @@ int virStorageEncryptionFormat(virBuffer *buf, virStorageEncryption *enc) { + const char *engine; const char *format; size_t i; @@ -335,7 +348,18 @@ virStorageEncryptionFormat(virBuffer *buf, "%s", _("unexpected encryption format")); return -1; } - virBufferAsprintf(buf, "<encryption format='%s'>\n", format); + if (enc->engine == VIR_STORAGE_ENCRYPTION_ENGINE_DEFAULT) { + virBufferAsprintf(buf, "<encryption format='%s'>\n", format); + } else { + if (!(engine = virStorageEncryptionEngineTypeToString(enc->engine))) { + virReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("unexpected encryption engine")); + return -1; + } + virBufferAsprintf(buf, "<encryption format='%s' engine='%s'>\n", + format, engine); + } + virBufferAdjustIndent(buf, 2); for (i = 0; i < enc->nsecrets; i++) { diff --git a/src/conf/storage_encryption_conf.h b/src/conf/storage_encryption_conf.h index 34adbd5f7b..e0ac0fe4bf 100644 --- a/src/conf/storage_encryption_conf.h +++ b/src/conf/storage_encryption_conf.h @@ -51,6 +51,14 @@ struct _virStorageEncryptionInfoDef { char *ivgen_hash; }; +typedef enum { + VIR_STORAGE_ENCRYPTION_ENGINE_DEFAULT = 0, + VIR_STORAGE_ENCRYPTION_ENGINE_QEMU, + + VIR_STORAGE_ENCRYPTION_ENGINE_LAST, +} virStorageEncryptionEngine; +VIR_ENUM_DECL(virStorageEncryptionEngine); + typedef enum { /* "default" is only valid for volume creation */ VIR_STORAGE_ENCRYPTION_FORMAT_DEFAULT = 0, @@ -63,6 +71,7 @@ VIR_ENUM_DECL(virStorageEncryptionFormat); typedef struct _virStorageEncryption virStorageEncryption; struct _virStorageEncryption { + virStorageEncryptionEngine engine; int format; /* virStorageEncryptionFormatType */ int payload_offset; diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c index b6d6d95692..0e2395278a 100644 --- a/src/qemu/qemu_block.c +++ b/src/qemu/qemu_block.c @@ -1314,6 +1314,7 @@ qemuBlockStorageSourceGetCryptoProps(virStorageSource *src, *encprops = NULL; if (!src->encryption || + src->encryption->engine != VIR_STORAGE_ENCRYPTION_ENGINE_QEMU || !srcpriv || !srcpriv->encinfo) return 0; @@ -1448,6 +1449,7 @@ qemuBlockStorageSourceGetBlockdevFormatProps(virStorageSource *src) * put a raw layer on top */ case VIR_STORAGE_FILE_RAW: if (src->encryption && + src->encryption->engine == VIR_STORAGE_ENCRYPTION_ENGINE_QEMU && src->encryption->format == VIR_STORAGE_ENCRYPTION_FORMAT_LUKS) { if (qemuBlockStorageSourceGetFormatLUKSProps(src, props) < 0) return NULL; diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 5ff602e3af..75cc656ed9 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -4770,6 +4770,18 @@ qemuDomainValidateStorageSource(virStorageSource *src, } } + if (src->encryption) { + switch (src->encryption->engine) { + case VIR_STORAGE_ENCRYPTION_ENGINE_QEMU: + break; + case VIR_STORAGE_ENCRYPTION_ENGINE_DEFAULT: + case VIR_STORAGE_ENCRYPTION_ENGINE_LAST: + virReportEnumRangeError(virStorageEncryptionEngine, + src->encryption->engine); + return -1; + } + } + return 0; } @@ -5222,6 +5234,8 @@ int qemuDomainDeviceDiskDefPostParse(virDomainDiskDef *disk, unsigned int parseFlags) { + virStorageSource *n; + /* set default disk types and drivers */ if (!virDomainDiskGetDriver(disk)) virDomainDiskSetDriver(disk, "qemu"); @@ -5236,6 +5250,12 @@ qemuDomainDeviceDiskDefPostParse(virDomainDiskDef *disk, disk->mirror->format == VIR_STORAGE_FILE_NONE) disk->mirror->format = VIR_STORAGE_FILE_RAW; + /* default disk encryption engine */ + for (n = disk->src; virStorageSourceIsBacking(n); n = n->backingStore) { + if (n->encryption && n->encryption->engine == VIR_STORAGE_ENCRYPTION_ENGINE_DEFAULT) + n->encryption->engine = VIR_STORAGE_ENCRYPTION_ENGINE_QEMU; + } + if (qemuDomainDeviceDiskDefPostParseRestoreSecAlias(disk, parseFlags) < 0) return -1; diff --git a/tests/qemustatusxml2xmldata/upgrade-out.xml b/tests/qemustatusxml2xmldata/upgrade-out.xml index f9476731f6..5218092cb9 100644 --- a/tests/qemustatusxml2xmldata/upgrade-out.xml +++ b/tests/qemustatusxml2xmldata/upgrade-out.xml @@ -316,7 +316,7 @@ <disk type='file' device='disk'> <driver name='qemu' type='qcow2'/> <source file='/var/lib/libvirt/images/b.qcow2'> - <encryption format='luks'> + <encryption format='luks' engine='qemu'> <secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccc2f80d6f'/> </encryption> <privateData> @@ -333,7 +333,7 @@ <disk type='file' device='disk'> <driver name='qemu' type='qcow2'/> <source file='/var/lib/libvirt/images/c.qcow2'> - <encryption format='luks'> + <encryption format='luks' engine='qemu'> <secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccc2f80d6f'/> </encryption> <privateData> @@ -354,7 +354,7 @@ <auth username='testuser-iscsi'> <secret type='iscsi' usage='testuser-iscsi-secret'/> </auth> - <encryption format='luks'> + <encryption format='luks' engine='qemu'> <secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccc2f80d6f'/> </encryption> <privateData> diff --git a/tests/qemuxml2argvdata/disk-nvme.xml b/tests/qemuxml2argvdata/disk-nvme.xml index 1ccbbfd598..9a5fafce7d 100644 --- a/tests/qemuxml2argvdata/disk-nvme.xml +++ b/tests/qemuxml2argvdata/disk-nvme.xml @@ -42,7 +42,7 @@ <driver name='qemu' type='qcow2' cache='none'/> <source type='pci' managed='no' namespace='2'> <address domain='0x0001' bus='0x02' slot='0x00' function='0x0'/> - <encryption format='luks'> + <encryption format='luks' engine='qemu'> <secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccc2f80d6f'/> </encryption> </source> diff --git a/tests/qemuxml2argvdata/encrypted-disk-usage.xml b/tests/qemuxml2argvdata/encrypted-disk-usage.xml index 7c2da9ee83..d2b87b94b6 100644 --- a/tests/qemuxml2argvdata/encrypted-disk-usage.xml +++ b/tests/qemuxml2argvdata/encrypted-disk-usage.xml @@ -18,7 +18,7 @@ <driver name='qemu' type='qcow2'/> <source file='/storage/guest_disks/encryptdisk'/> <target dev='vda' bus='virtio'/> - <encryption format='luks'> + <encryption format='luks' engine='qemu'> <secret type='passphrase' usage='/storage/guest_disks/encryptdisk'/> </encryption> <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> diff --git a/tests/qemuxml2argvdata/luks-disks.xml b/tests/qemuxml2argvdata/luks-disks.xml index ae6d3d996c..1c76f0dc26 100644 --- a/tests/qemuxml2argvdata/luks-disks.xml +++ b/tests/qemuxml2argvdata/luks-disks.xml @@ -18,7 +18,7 @@ <driver name='qemu' type='raw'/> <source file='/storage/guest_disks/encryptdisk'/> <target dev='vda' bus='virtio'/> - <encryption format='luks'> + <encryption format='luks' engine='qemu'> <secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccc2f80d6f'/> </encryption> <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> @@ -27,7 +27,7 @@ <driver name='qemu' type='raw'/> <source file='/storage/guest_disks/encryptdisk2'/> <target dev='vdb' bus='virtio'/> - <encryption format='luks'> + <encryption format='luks' engine='qemu'> <secret type='passphrase' usage='/storage/guest_disks/encryptdisk2'/> </encryption> <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/> diff --git a/tests/qemuxml2argvdata/user-aliases.xml b/tests/qemuxml2argvdata/user-aliases.xml index 47bfc56e73..10b7749521 100644 --- a/tests/qemuxml2argvdata/user-aliases.xml +++ b/tests/qemuxml2argvdata/user-aliases.xml @@ -55,7 +55,7 @@ <driver name='qemu' type='qcow2'/> <source file='/var/lib/libvirt/images/OtherDemo.img'/> <target dev='vdb' bus='virtio'/> - <encryption format='luks'> + <encryption format='luks' engine='qemu'> <secret type='passphrase' uuid='e78d4b51-a2af-485f-b0f5-afca709a80f4'/> </encryption> <alias name='ua-myEncryptedDisk1'/> diff --git a/tests/qemuxml2xmloutdata/disk-slices.x86_64-latest.xml b/tests/qemuxml2xmloutdata/disk-slices.x86_64-latest.xml index be5cd25084..a058cbad61 100644 --- a/tests/qemuxml2xmloutdata/disk-slices.x86_64-latest.xml +++ b/tests/qemuxml2xmloutdata/disk-slices.x86_64-latest.xml @@ -49,7 +49,7 @@ <slices> <slice type='storage' offset='1234' size='321'/> </slices> - <encryption format='luks'> + <encryption format='luks' engine='qemu'> <secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccc2f80d6f'/> </encryption> </source> @@ -75,7 +75,7 @@ <slices> <slice type='storage' offset='1234' size='321'/> </slices> - <encryption format='luks'> + <encryption format='luks' engine='qemu'> <secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccc2f80d6f'/> </encryption> </source> diff --git a/tests/qemuxml2xmloutdata/encrypted-disk.xml b/tests/qemuxml2xmloutdata/encrypted-disk.xml index 06f2c5b47c..e30c8a36e8 100644 --- a/tests/qemuxml2xmloutdata/encrypted-disk.xml +++ b/tests/qemuxml2xmloutdata/encrypted-disk.xml @@ -18,7 +18,7 @@ <driver name='qemu' type='qcow2'/> <source file='/storage/guest_disks/encryptdisk'/> <target dev='vda' bus='virtio'/> - <encryption format='luks'> + <encryption format='luks' engine='qemu'> <secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccc2f80d6f'/> </encryption> <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> diff --git a/tests/qemuxml2xmloutdata/luks-disks-source-qcow2.x86_64-latest.xml b/tests/qemuxml2xmloutdata/luks-disks-source-qcow2.x86_64-latest.xml index 5f600f5ba7..7f98dd597e 100644 --- a/tests/qemuxml2xmloutdata/luks-disks-source-qcow2.x86_64-latest.xml +++ b/tests/qemuxml2xmloutdata/luks-disks-source-qcow2.x86_64-latest.xml @@ -20,7 +20,7 @@ <disk type='file' device='disk'> <driver name='qemu' type='qcow2'/> <source file='/storage/guest_disks/encryptdisk'> - <encryption format='luks'> + <encryption format='luks' engine='qemu'> <secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccc2f80d6f'/> </encryption> </source> @@ -30,7 +30,7 @@ <disk type='file' device='disk'> <driver name='qemu' type='qcow2'/> <source file='/storage/guest_disks/encryptdisk2'> - <encryption format='luks'> + <encryption format='luks' engine='qemu'> <secret type='passphrase' usage='/storage/guest_disks/encryptdisk2'/> </encryption> </source> @@ -44,7 +44,7 @@ <auth username='myname'> <secret type='iscsi' uuid='0a81f5b2-8403-7b23-c8d6-21ccc2f80e80'/> </auth> - <encryption format='luks'> + <encryption format='luks' engine='qemu'> <secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccc2f80f77'/> </encryption> </source> @@ -54,7 +54,7 @@ <disk type='volume' device='disk'> <driver name='qemu' type='qcow2'/> <source pool='pool-iscsi' volume='unit:0:0:3' mode='direct'> - <encryption format='luks'> + <encryption format='luks' engine='qemu'> <secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccc2f80f80'/> </encryption> </source> @@ -67,7 +67,7 @@ <host name='mon1.example.org' port='6321'/> <host name='mon2.example.org' port='6322'/> <host name='mon3.example.org' port='6322'/> - <encryption format='luks'> + <encryption format='luks' engine='qemu'> <secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccc2f80fb0'/> </encryption> </source> @@ -77,14 +77,14 @@ <disk type='file' device='disk'> <driver name='qemu' type='qcow2'/> <source file='/storage/guest_disks/encryptdisk5'> - <encryption format='luks'> + <encryption format='luks' engine='qemu'> <secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccc2f80d6f'/> </encryption> </source> <backingStore type='file'> <format type='qcow2'/> <source file='/storage/guest_disks/base.qcow2'> - <encryption format='luks'> + <encryption format='luks' engine='qemu'> <secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccc2f80d6f'/> </encryption> </source> diff --git a/tests/qemuxml2xmloutdata/luks-disks-source.xml b/tests/qemuxml2xmloutdata/luks-disks-source.xml index 5333d4ac6e..891b5d9d17 100644 --- a/tests/qemuxml2xmloutdata/luks-disks-source.xml +++ b/tests/qemuxml2xmloutdata/luks-disks-source.xml @@ -17,7 +17,7 @@ <disk type='file' device='disk'> <driver name='qemu' type='raw'/> <source file='/storage/guest_disks/encryptdisk'> - <encryption format='luks'> + <encryption format='luks' engine='qemu'> <secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccc2f80d6f'/> </encryption> </source> @@ -27,7 +27,7 @@ <disk type='file' device='disk'> <driver name='qemu' type='raw'/> <source file='/storage/guest_disks/encryptdisk2'> - <encryption format='luks'> + <encryption format='luks' engine='qemu'> <secret type='passphrase' usage='/storage/guest_disks/encryptdisk2'/> </encryption> </source> @@ -41,7 +41,7 @@ <auth username='myname'> <secret type='iscsi' uuid='0a81f5b2-8403-7b23-c8d6-21ccc2f80e80'/> </auth> - <encryption format='luks'> + <encryption format='luks' engine='qemu'> <secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccc2f80f77'/> </encryption> </source> @@ -51,7 +51,7 @@ <disk type='volume' device='disk'> <driver name='qemu' type='raw'/> <source pool='pool-iscsi' volume='unit:0:0:3' mode='direct'> - <encryption format='luks'> + <encryption format='luks' engine='qemu'> <secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccc2f80f80'/> </encryption> </source> @@ -64,7 +64,7 @@ <host name='mon1.example.org' port='6321'/> <host name='mon2.example.org' port='6322'/> <host name='mon3.example.org' port='6322'/> - <encryption format='luks'> + <encryption format='luks' engine='qemu'> <secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccc2f80fb0'/> </encryption> </source> -- 2.25.1

rbd encryption is new in qemu 6.1.0. This commit adds a new encryption engine property which allows the user to use this new encryption engine. Signed-off-by: Or Ozeri <oro@il.ibm.com> --- docs/formatstorageencryption.html.in | 11 ++- docs/schemas/storagecommon.rng | 1 + src/conf/storage_encryption_conf.c | 2 +- src/conf/storage_encryption_conf.h | 1 + src/qemu/qemu_block.c | 30 ++++++++ src/qemu/qemu_domain.c | 38 ++++++++++ ...sk-network-rbd-encryption.x86_64-6.0.0.err | 1 + ...-network-rbd-encryption.x86_64-latest.args | 45 ++++++++++++ .../disk-network-rbd-encryption.xml | 63 +++++++++++++++++ tests/qemuxml2argvtest.c | 2 + ...k-network-rbd-encryption.x86_64-latest.xml | 70 +++++++++++++++++++ tests/qemuxml2xmltest.c | 1 + 12 files changed, 263 insertions(+), 2 deletions(-) create mode 100644 tests/qemuxml2argvdata/disk-network-rbd-encryption.x86_64-6.0.0.err create mode 100644 tests/qemuxml2argvdata/disk-network-rbd-encryption.x86_64-latest.args create mode 100644 tests/qemuxml2argvdata/disk-network-rbd-encryption.xml create mode 100644 tests/qemuxml2xmloutdata/disk-network-rbd-encryption.x86_64-latest.xml diff --git a/docs/formatstorageencryption.html.in b/docs/formatstorageencryption.html.in index 178fcd0d7c..fb04a6a0ad 100644 --- a/docs/formatstorageencryption.html.in +++ b/docs/formatstorageencryption.html.in @@ -27,7 +27,16 @@ The <code>encryption</code> tag supports an optional <code>engine</code> tag, which allows selecting which component actually handles the encryption. Currently defined values of <code>engine</code> are - <code>qemu</code>. + <code>qemu</code> and <code>librbd</code>. + Both <code>qemu</code> and <code>librbd</code> require using the qemu + driver. + The <code>librbd</code> engine requires qemu version >= 6.1.0, + and is only applicable for RBD network disks. + If the engine tag is not specified, the <code>qemu</code> engine will be + used by default (assuming the qemu driver is used). + Note that <code>librbd</code> 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 <code>engine</code> tag. </p> <p> The <code>encryption</code> tag can currently contain a sequence of diff --git a/docs/schemas/storagecommon.rng b/docs/schemas/storagecommon.rng index 60dcfac06c..3ddff02e43 100644 --- a/docs/schemas/storagecommon.rng +++ b/docs/schemas/storagecommon.rng @@ -19,6 +19,7 @@ <attribute name="engine"> <choice> <value>qemu</value> + <value>librbd</value> </choice> </attribute> </optional> diff --git a/src/conf/storage_encryption_conf.c b/src/conf/storage_encryption_conf.c index 7fd601e4a2..d45ad717a0 100644 --- a/src/conf/storage_encryption_conf.c +++ b/src/conf/storage_encryption_conf.c @@ -49,7 +49,7 @@ VIR_ENUM_IMPL(virStorageEncryptionFormat, VIR_ENUM_IMPL(virStorageEncryptionEngine, VIR_STORAGE_ENCRYPTION_ENGINE_LAST, - "default", "qemu", + "default", "qemu", "librbd", ); static void diff --git a/src/conf/storage_encryption_conf.h b/src/conf/storage_encryption_conf.h index e0ac0fe4bf..0931618608 100644 --- a/src/conf/storage_encryption_conf.h +++ b/src/conf/storage_encryption_conf.h @@ -54,6 +54,7 @@ struct _virStorageEncryptionInfoDef { typedef enum { VIR_STORAGE_ENCRYPTION_ENGINE_DEFAULT = 0, VIR_STORAGE_ENCRYPTION_ENGINE_QEMU, + VIR_STORAGE_ENCRYPTION_ENGINE_LIBRBD, VIR_STORAGE_ENCRYPTION_ENGINE_LAST, } virStorageEncryptionEngine; diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c index 0e2395278a..4af06aea1b 100644 --- a/src/qemu/qemu_block.c +++ b/src/qemu/qemu_block.c @@ -875,6 +875,8 @@ qemuBlockStorageSourceGetRBDProps(virStorageSource *src, qemuDomainStorageSourcePrivate *srcPriv = QEMU_DOMAIN_STORAGE_SOURCE_PRIVATE(src); g_autoptr(virJSONValue) servers = NULL; virJSONValue *ret = NULL; + g_autoptr(virJSONValue) encrypt = NULL; + const char *encformat; const char *username = NULL; g_autoptr(virJSONValue) authmodes = NULL; g_autoptr(virJSONValue) mode = NULL; @@ -899,12 +901,40 @@ qemuBlockStorageSourceGetRBDProps(virStorageSource *src, return NULL; } + if (src->encryption && + src->encryption->engine == VIR_STORAGE_ENCRYPTION_ENGINE_LIBRBD) { + switch ((virStorageEncryptionFormatType) src->encryption->format) { + case VIR_STORAGE_ENCRYPTION_FORMAT_LUKS: + encformat = "luks"; + break; + + case VIR_STORAGE_ENCRYPTION_FORMAT_QCOW: + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("librbd encryption engine only supports luks/luks2 formats")); + return NULL; + + case VIR_STORAGE_ENCRYPTION_FORMAT_DEFAULT: + case VIR_STORAGE_ENCRYPTION_FORMAT_LAST: + default: + virReportEnumRangeError(virStorageEncryptionFormatType, + src->encryption->format); + return NULL; + } + + if (virJSONValueObjectCreate(&encrypt, + "s:format", encformat, + "s:key-secret", srcPriv->encinfo->alias, + NULL) < 0) + return NULL; + } + if (virJSONValueObjectCreate(&ret, "s:pool", src->volume, "s:image", src->path, "S:snapshot", src->snapshot, "S:conf", src->configFile, "A:server", &servers, + "A:encrypt", &encrypt, "S:user", username, "A:auth-client-required", &authmodes, "S:key-secret", keysecret, diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 75cc656ed9..71cebec4e8 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -4773,6 +4773,44 @@ qemuDomainValidateStorageSource(virStorageSource *src, if (src->encryption) { switch (src->encryption->engine) { case VIR_STORAGE_ENCRYPTION_ENGINE_QEMU: + switch ((virStorageEncryptionFormatType) src->encryption->format) { + case VIR_STORAGE_ENCRYPTION_FORMAT_LUKS: + case VIR_STORAGE_ENCRYPTION_FORMAT_QCOW: + break; + + case VIR_STORAGE_ENCRYPTION_FORMAT_DEFAULT: + case VIR_STORAGE_ENCRYPTION_FORMAT_LAST: + default: + virReportEnumRangeError(virStorageEncryptionFormatType, + src->encryption->format); + return -1; + } + + break; + case VIR_STORAGE_ENCRYPTION_ENGINE_LIBRBD: + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_RBD_ENCRYPTION)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("librbd encryption is not supported by this QEMU binary")); + return -1; + } + + switch ((virStorageEncryptionFormatType) src->encryption->format) { + case VIR_STORAGE_ENCRYPTION_FORMAT_LUKS: + break; + + case VIR_STORAGE_ENCRYPTION_FORMAT_QCOW: + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("librbd encryption engine only supports luks/luks2 formats")); + return -1; + + case VIR_STORAGE_ENCRYPTION_FORMAT_DEFAULT: + case VIR_STORAGE_ENCRYPTION_FORMAT_LAST: + default: + virReportEnumRangeError(virStorageEncryptionFormatType, + src->encryption->format); + return -1; + } + break; case VIR_STORAGE_ENCRYPTION_ENGINE_DEFAULT: case VIR_STORAGE_ENCRYPTION_ENGINE_LAST: diff --git a/tests/qemuxml2argvdata/disk-network-rbd-encryption.x86_64-6.0.0.err b/tests/qemuxml2argvdata/disk-network-rbd-encryption.x86_64-6.0.0.err new file mode 100644 index 0000000000..edd8481a20 --- /dev/null +++ b/tests/qemuxml2argvdata/disk-network-rbd-encryption.x86_64-6.0.0.err @@ -0,0 +1 @@ +unsupported configuration: librbd encryption is not supported by this QEMU binary diff --git a/tests/qemuxml2argvdata/disk-network-rbd-encryption.x86_64-latest.args b/tests/qemuxml2argvdata/disk-network-rbd-encryption.x86_64-latest.args new file mode 100644 index 0000000000..474c245d60 --- /dev/null +++ b/tests/qemuxml2argvdata/disk-network-rbd-encryption.x86_64-latest.args @@ -0,0 +1,45 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/tmp/lib/domain--1-encryptdisk \ +USER=test \ +LOGNAME=test \ +XDG_DATA_HOME=/tmp/lib/domain--1-encryptdisk/.local/share \ +XDG_CACHE_HOME=/tmp/lib/domain--1-encryptdisk/.cache \ +XDG_CONFIG_HOME=/tmp/lib/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":"/tmp/lib/domain--1-encryptdisk/master-key.aes"}' \ +-machine pc-i440fx-2.1,accel=tcg,usb=off,dump-guest-core=off,memory-backend=pc.ram \ +-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 \ +-no-acpi \ +-boot strict=on \ +-device '{"driver":"piix3-usb-uhci","id":"usb","bus":"pci.0","addr":"0x1.0x2"}' \ +-object '{"qom-type":"secret","id":"libvirt-3-format-encryption-secret0","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"}],"node-name":"libvirt-3-storage","auto-read-only":true,"discard":"unmap"}' \ +-blockdev '{"node-name":"libvirt-3-format","read-only":false,"driver":"luks","key-secret":"libvirt-3-format-encryption-secret0","file":"libvirt-3-storage"}' \ +-device '{"driver":"virtio-blk-pci","bus":"pci.0","addr":"0x2","drive":"libvirt-3-format","id":"virtio-disk0","bootindex":1}' \ +-object '{"qom-type":"secret","id":"libvirt-2-format-encryption-secret0","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"}],"node-name":"libvirt-2-storage","auto-read-only":true,"discard":"unmap"}' \ +-blockdev '{"node-name":"libvirt-2-format","read-only":false,"driver":"luks","key-secret":"libvirt-2-format-encryption-secret0","file":"libvirt-2-storage"}' \ +-device '{"driver":"virtio-blk-pci","bus":"pci.0","addr":"0x4","drive":"libvirt-2-format","id":"virtio-disk1"}' \ +-object '{"qom-type":"secret","id":"libvirt-1-format-encryption-secret0","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"},"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":"0x5","drive":"libvirt-1-format","id":"virtio-disk2"}' \ +-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 diff --git a/tests/qemuxml2argvdata/disk-network-rbd-encryption.xml b/tests/qemuxml2argvdata/disk-network-rbd-encryption.xml new file mode 100644 index 0000000000..d8c2d3dbe2 --- /dev/null +++ b/tests/qemuxml2argvdata/disk-network-rbd-encryption.xml @@ -0,0 +1,63 @@ +<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'> + <secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccc2f80fb0'/> + </encryption> + </source> + <target dev='vda' bus='virtio'/> + </disk> + <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='qemu'> + <secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccc2f80fb0'/> + </encryption> + </source> + <target dev='vdb' bus='virtio'/> + </disk> + <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'/> + </encryption> + </source> + <target dev='vdc' 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> diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index e209b48fce..df7cfe020e 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -1344,6 +1344,8 @@ mymain(void) DO_TEST_CAPS_LATEST("disk-network-gluster"); DO_TEST_CAPS_VER("disk-network-rbd", "2.12.0"); 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_FAILURE("disk-network-rbd-no-colon", "4.1.0"); DO_TEST_CAPS_LATEST("disk-network-rbd-no-colon"); DO_TEST_CAPS_VER("disk-network-sheepdog", "2.12.0"); diff --git a/tests/qemuxml2xmloutdata/disk-network-rbd-encryption.x86_64-latest.xml b/tests/qemuxml2xmloutdata/disk-network-rbd-encryption.x86_64-latest.xml new file mode 100644 index 0000000000..d4942718bb --- /dev/null +++ b/tests/qemuxml2xmloutdata/disk-network-rbd-encryption.x86_64-latest.xml @@ -0,0 +1,70 @@ +<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='qemu'> + <secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccc2f80fb0'/> + </encryption> + </source> + <target dev='vda' bus='virtio'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + </disk> + <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='qemu'> + <secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccc2f80fb0'/> + </encryption> + </source> + <target dev='vdb' bus='virtio'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> + </disk> + <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'/> + </encryption> + </source> + <target dev='vdc' bus='virtio'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x05' 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> diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index b0a1212a54..90813f8cd8 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -315,6 +315,7 @@ mymain(void) QEMU_CAPS_SCSI_BLOCK); DO_TEST_NOCAPS("disk-network-gluster"); DO_TEST_NOCAPS("disk-network-rbd"); + DO_TEST_CAPS_LATEST("disk-network-rbd-encryption"); DO_TEST_NOCAPS("disk-network-source-auth"); DO_TEST_NOCAPS("disk-network-sheepdog"); DO_TEST_NOCAPS("disk-network-vxhs"); -- 2.25.1

This commit extends libvirt XML configuration to support luks2 encryption format. This means that <encryption format="luks2" engine="librbd"> becomes valid. Currently librbd is the only engine that supports this new format. Signed-off-by: Or Ozeri <oro@il.ibm.com> --- docs/formatstorageencryption.html.in | 14 +++++++++++++- docs/schemas/storagecommon.rng | 1 + src/conf/storage_encryption_conf.c | 2 +- src/conf/storage_encryption_conf.h | 1 + src/qemu/qemu_block.c | 9 +++++++++ src/qemu/qemu_domain.c | 9 ++++++++- ...isk-network-rbd-encryption.x86_64-latest.args | 16 ++++++++++------ .../disk-network-rbd-encryption.xml | 12 ++++++++++++ ...disk-network-rbd-encryption.x86_64-latest.xml | 13 +++++++++++++ 9 files changed, 68 insertions(+), 9 deletions(-) diff --git a/docs/formatstorageencryption.html.in b/docs/formatstorageencryption.html.in index fb04a6a0ad..86d884f93d 100644 --- a/docs/formatstorageencryption.html.in +++ b/docs/formatstorageencryption.html.in @@ -18,7 +18,7 @@ is <code>encryption</code>, with a mandatory attribute <code>format</code>. Currently defined values of <code>format</code> are <code>default</code>, <code>qcow</code>, - and <code>luks</code>. + <code>luks</code>, and <code>luks2</code>. Each value of <code>format</code> implies some expectations about the content of the <code>encryption</code> tag. Other format values may be defined in the future. @@ -125,6 +125,18 @@ </dd> </dl> + <h3><a id="StorageEncryptionLuks2">"luks2" format</a></h3> + <p> + The <code>luks2</code> format is currently supported only by the + <code>librbd</code> engine, and can only be applied to RBD network disks. + Since the <code>librbd</code> engine is currently not supported by the + 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 + <code><secret type='passphrase'...></code> element is expected. + </p> + <h2><a id="example">Examples</a></h2> diff --git a/docs/schemas/storagecommon.rng b/docs/schemas/storagecommon.rng index 3ddff02e43..591a158209 100644 --- a/docs/schemas/storagecommon.rng +++ b/docs/schemas/storagecommon.rng @@ -13,6 +13,7 @@ <value>default</value> <value>qcow</value> <value>luks</value> + <value>luks2</value> </choice> </attribute> <optional> diff --git a/src/conf/storage_encryption_conf.c b/src/conf/storage_encryption_conf.c index d45ad717a0..a65ef1f8a2 100644 --- a/src/conf/storage_encryption_conf.c +++ b/src/conf/storage_encryption_conf.c @@ -44,7 +44,7 @@ VIR_ENUM_IMPL(virStorageEncryptionSecret, VIR_ENUM_IMPL(virStorageEncryptionFormat, VIR_STORAGE_ENCRYPTION_FORMAT_LAST, - "default", "qcow", "luks", + "default", "qcow", "luks", "luks2", ); VIR_ENUM_IMPL(virStorageEncryptionEngine, diff --git a/src/conf/storage_encryption_conf.h b/src/conf/storage_encryption_conf.h index 0931618608..312599ad44 100644 --- a/src/conf/storage_encryption_conf.h +++ b/src/conf/storage_encryption_conf.h @@ -65,6 +65,7 @@ typedef enum { VIR_STORAGE_ENCRYPTION_FORMAT_DEFAULT = 0, VIR_STORAGE_ENCRYPTION_FORMAT_QCOW, /* Both qcow and qcow2 */ VIR_STORAGE_ENCRYPTION_FORMAT_LUKS, + VIR_STORAGE_ENCRYPTION_FORMAT_LUKS2, VIR_STORAGE_ENCRYPTION_FORMAT_LAST, } virStorageEncryptionFormatType; diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c index 4af06aea1b..34fdec2c4b 100644 --- a/src/qemu/qemu_block.c +++ b/src/qemu/qemu_block.c @@ -908,6 +908,10 @@ qemuBlockStorageSourceGetRBDProps(virStorageSource *src, encformat = "luks"; break; + case VIR_STORAGE_ENCRYPTION_FORMAT_LUKS2: + encformat = "luks2"; + break; + case VIR_STORAGE_ENCRYPTION_FORMAT_QCOW: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("librbd encryption engine only supports luks/luks2 formats")); @@ -1358,6 +1362,11 @@ qemuBlockStorageSourceGetCryptoProps(virStorageSource *src, encformat = "luks"; break; + case VIR_STORAGE_ENCRYPTION_FORMAT_LUKS2: + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("luks2 is currently not supported by the qemu encryption engine")); + return -1; + case VIR_STORAGE_ENCRYPTION_FORMAT_DEFAULT: case VIR_STORAGE_ENCRYPTION_FORMAT_LAST: default: diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 71cebec4e8..4080671dd8 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -1188,7 +1188,8 @@ static bool qemuDomainDiskHasEncryptionSecret(virStorageSource *src) { if (!virStorageSourceIsEmpty(src) && src->encryption && - src->encryption->format == VIR_STORAGE_ENCRYPTION_FORMAT_LUKS && + (src->encryption->format == VIR_STORAGE_ENCRYPTION_FORMAT_LUKS || + src->encryption->format == VIR_STORAGE_ENCRYPTION_FORMAT_LUKS2) && src->encryption->nsecrets > 0) return true; @@ -4778,6 +4779,11 @@ qemuDomainValidateStorageSource(virStorageSource *src, case VIR_STORAGE_ENCRYPTION_FORMAT_QCOW: break; + case VIR_STORAGE_ENCRYPTION_FORMAT_LUKS2: + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("luks2 is currently not supported by the qemu encryption engine")); + return -1; + case VIR_STORAGE_ENCRYPTION_FORMAT_DEFAULT: case VIR_STORAGE_ENCRYPTION_FORMAT_LAST: default: @@ -4796,6 +4802,7 @@ qemuDomainValidateStorageSource(virStorageSource *src, switch ((virStorageEncryptionFormatType) src->encryption->format) { case VIR_STORAGE_ENCRYPTION_FORMAT_LUKS: + case VIR_STORAGE_ENCRYPTION_FORMAT_LUKS2: break; case VIR_STORAGE_ENCRYPTION_FORMAT_QCOW: diff --git a/tests/qemuxml2argvdata/disk-network-rbd-encryption.x86_64-latest.args b/tests/qemuxml2argvdata/disk-network-rbd-encryption.x86_64-latest.args index 474c245d60..00f6168e96 100644 --- a/tests/qemuxml2argvdata/disk-network-rbd-encryption.x86_64-latest.args +++ b/tests/qemuxml2argvdata/disk-network-rbd-encryption.x86_64-latest.args @@ -27,18 +27,22 @@ XDG_CONFIG_HOME=/tmp/lib/domain--1-encryptdisk/.config \ -no-acpi \ -boot strict=on \ -device '{"driver":"piix3-usb-uhci","id":"usb","bus":"pci.0","addr":"0x1.0x2"}' \ +-object '{"qom-type":"secret","id":"libvirt-4-format-encryption-secret0","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"}],"node-name":"libvirt-4-storage","auto-read-only":true,"discard":"unmap"}' \ +-blockdev '{"node-name":"libvirt-4-format","read-only":false,"driver":"luks","key-secret":"libvirt-4-format-encryption-secret0","file":"libvirt-4-storage"}' \ +-device '{"driver":"virtio-blk-pci","bus":"pci.0","addr":"0x2","drive":"libvirt-4-format","id":"virtio-disk0","bootindex":1}' \ -object '{"qom-type":"secret","id":"libvirt-3-format-encryption-secret0","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"}],"node-name":"libvirt-3-storage","auto-read-only":true,"discard":"unmap"}' \ -blockdev '{"node-name":"libvirt-3-format","read-only":false,"driver":"luks","key-secret":"libvirt-3-format-encryption-secret0","file":"libvirt-3-storage"}' \ --device '{"driver":"virtio-blk-pci","bus":"pci.0","addr":"0x2","drive":"libvirt-3-format","id":"virtio-disk0","bootindex":1}' \ +-device '{"driver":"virtio-blk-pci","bus":"pci.0","addr":"0x4","drive":"libvirt-3-format","id":"virtio-disk1"}' \ -object '{"qom-type":"secret","id":"libvirt-2-format-encryption-secret0","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"}],"node-name":"libvirt-2-storage","auto-read-only":true,"discard":"unmap"}' \ --blockdev '{"node-name":"libvirt-2-format","read-only":false,"driver":"luks","key-secret":"libvirt-2-format-encryption-secret0","file":"libvirt-2-storage"}' \ --device '{"driver":"virtio-blk-pci","bus":"pci.0","addr":"0x4","drive":"libvirt-2-format","id":"virtio-disk1"}' \ +-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-2-format-encryption-secret0"},"node-name":"libvirt-2-storage","auto-read-only":true,"discard":"unmap"}' \ +-blockdev '{"node-name":"libvirt-2-format","read-only":false,"driver":"raw","file":"libvirt-2-storage"}' \ +-device '{"driver":"virtio-blk-pci","bus":"pci.0","addr":"0x5","drive":"libvirt-2-format","id":"virtio-disk2"}' \ -object '{"qom-type":"secret","id":"libvirt-1-format-encryption-secret0","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"},"node-name":"libvirt-1-storage","auto-read-only":true,"discard":"unmap"}' \ +-blockdev '{"driver":"rbd","pool":"pool","image":"image2","server":[{"host":"mon1.example.org","port":"6321"},{"host":"mon2.example.org","port":"6322"},{"host":"mon3.example.org","port":"6322"}],"encrypt":{"format":"luks2","key-secret":"libvirt-1-format-encryption-secret0"},"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":"0x5","drive":"libvirt-1-format","id":"virtio-disk2"}' \ +-device '{"driver":"virtio-blk-pci","bus":"pci.0","addr":"0x6","drive":"libvirt-1-format","id":"virtio-disk3"}' \ -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 \ diff --git a/tests/qemuxml2argvdata/disk-network-rbd-encryption.xml b/tests/qemuxml2argvdata/disk-network-rbd-encryption.xml index d8c2d3dbe2..eeadbfeeba 100644 --- a/tests/qemuxml2argvdata/disk-network-rbd-encryption.xml +++ b/tests/qemuxml2argvdata/disk-network-rbd-encryption.xml @@ -50,6 +50,18 @@ </source> <target dev='vdc' bus='virtio'/> </disk> + <disk type='network' device='disk'> + <driver name='qemu' type='raw'/> + <source protocol='rbd' name='pool/image2'> + <host name='mon1.example.org' port='6321'/> + <host name='mon2.example.org' port='6322'/> + <host name='mon3.example.org' port='6322'/> + <encryption format='luks2' engine='librbd'> + <secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccc2f80fb0'/> + </encryption> + </source> + <target dev='vdd' bus='virtio'/> + </disk> <controller type='usb' index='0'> <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> </controller> diff --git a/tests/qemuxml2xmloutdata/disk-network-rbd-encryption.x86_64-latest.xml b/tests/qemuxml2xmloutdata/disk-network-rbd-encryption.x86_64-latest.xml index d4942718bb..a91504202a 100644 --- a/tests/qemuxml2xmloutdata/disk-network-rbd-encryption.x86_64-latest.xml +++ b/tests/qemuxml2xmloutdata/disk-network-rbd-encryption.x86_64-latest.xml @@ -56,6 +56,19 @@ <target dev='vdc' bus='virtio'/> <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/> </disk> + <disk type='network' device='disk'> + <driver name='qemu' type='raw'/> + <source protocol='rbd' name='pool/image2'> + <host name='mon1.example.org' port='6321'/> + <host name='mon2.example.org' port='6322'/> + <host name='mon3.example.org' port='6322'/> + <encryption format='luks2' engine='librbd'> + <secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccc2f80fb0'/> + </encryption> + </source> + <target dev='vdd' bus='virtio'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/> + </disk> <controller type='usb' index='0' model='piix3-uhci'> <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> </controller> -- 2.25.1

Hi Or, I have a question about this feature. For rbd encryption in ceph, is it introduced from ceph-v16.2.0? Does it require the ceph cluster side >= this version? On Sun, Oct 24, 2021 at 5:54 PM Or Ozeri <oro@il.ibm.com> wrote:
v5: rebased + nit fixes suggested by Peter v4: - added disk post parse to image creation flow in qemublocktest (since more tests failed after adding engine validation) - removed symlink changes - added luks2 and engine documentation - switched to using enum engine instead of int - added validation for encryption engine and formats v3: rebased on master v2: addressed (hopefully) all of Peter's v1 comments (thanks Peter!)
Feel free to make any other changes before pushing. Thanks!
Or Ozeri (5): qemu: add disk post parse to qemublocktest qemu: capablities: Detect presence of 'rbd-encryption' as QEMU_CAPS_RBD_ENCRYPTION conf: add encryption engine property qemu: add librbd encryption engine conf: add luks2 encryption format
docs/formatstorageencryption.html.in | 29 ++++++- docs/schemas/domainbackup.rng | 7 ++ docs/schemas/storagecommon.rng | 9 ++ src/conf/storage_encryption_conf.c | 28 ++++++- src/conf/storage_encryption_conf.h | 11 +++ src/qemu/qemu_block.c | 41 +++++++++ src/qemu/qemu_capabilities.c | 2 + src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_domain.c | 69 ++++++++++++++- src/qemu/qemu_domain.h | 3 + tests/qemublocktest.c | 29 +++---- .../caps_6.1.0.x86_64.xml | 1 + .../caps_6.2.0.x86_64.xml | 1 + tests/qemustatusxml2xmldata/upgrade-out.xml | 6 +- ...sk-network-rbd-encryption.x86_64-6.0.0.err | 1 + ...-network-rbd-encryption.x86_64-latest.args | 49 +++++++++++ .../disk-network-rbd-encryption.xml | 75 +++++++++++++++++ tests/qemuxml2argvdata/disk-nvme.xml | 2 +- .../qemuxml2argvdata/encrypted-disk-usage.xml | 2 +- tests/qemuxml2argvdata/luks-disks.xml | 4 +- tests/qemuxml2argvdata/user-aliases.xml | 2 +- tests/qemuxml2argvtest.c | 2 + ...k-network-rbd-encryption.x86_64-latest.xml | 83 +++++++++++++++++++ .../disk-slices.x86_64-latest.xml | 4 +- tests/qemuxml2xmloutdata/encrypted-disk.xml | 2 +- .../luks-disks-source-qcow2.x86_64-latest.xml | 14 ++-- .../qemuxml2xmloutdata/luks-disks-source.xml | 10 +-- tests/qemuxml2xmltest.c | 1 + 28 files changed, 443 insertions(+), 45 deletions(-) create mode 100644 tests/qemuxml2argvdata/disk-network-rbd-encryption.x86_64-6.0.0.err create mode 100644 tests/qemuxml2argvdata/disk-network-rbd-encryption.x86_64-latest.args create mode 100644 tests/qemuxml2argvdata/disk-network-rbd-encryption.xml create mode 100644 tests/qemuxml2xmloutdata/disk-network-rbd-encryption.x86_64-latest.xml
-- 2.25.1
participants (4)
-
Han Han
-
Or Ozeri
-
Or Ozeri
-
Peter Krempa