diff --git a/src/storage/storage_util.c b/src/storage/storage_util.c index 92d5c09a90..7d3db6a449 100644 --- a/src/storage/storage_util.c +++ b/src/storage/storage_util.c @@ -1084,6 +1084,7 @@ virStorageBackendCreateQemuImgCmdFromVol(virStoragePoolObjPtr pool, unsigned int flags, const char *create_tool, const char *secretPath, + const char *inputSecretPath, virStorageVolEncryptConvertStep convertStep) { virCommandPtr cmd = NULL; @@ -1101,6 +1102,8 @@ virStorageBackendCreateQemuImgCmdFromVol(virStoragePoolObjPtr pool, .secretAlias = NULL, }; virStorageEncryptionPtr enc = vol->target.encryption; + char *inputSecretAlias = NULL; + virStorageEncryptionPtr inputenc = inputvol ? inputvol->target.encryption : NULL; virStorageEncryptionInfoDefPtr encinfo = NULL; virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA, NULL); @@ -1114,6 +1117,12 @@ virStorageBackendCreateQemuImgCmdFromVol(virStoragePoolObjPtr pool, goto error; } + if (inputenc && inputenc->format != VIR_STORAGE_ENCRYPTION_FORMAT_LUKS) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("encryption format of inputvol must be LUKS")); + goto error; + } + if (virStorageBackendCreateQemuImgSetInfo(pool, vol, inputvol, convertStep, &info) < 0) goto error; @@ -1153,6 +1162,20 @@ virStorageBackendCreateQemuImgCmdFromVol(virStoragePoolObjPtr pool, encinfo = &enc->encinfo; } + if (inputenc && convertStep == VIR_STORAGE_VOL_ENCRYPT_CONVERT) { + if (!inputSecretPath) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("path to inputvol secret data file is required")); + goto error; + } + if (virAsprintf(&inputSecretAlias, "%s_encrypt0", + inputvol->name) < 0) + goto error; + if (storageBackendCreateQemuImgSecretObject(cmd, inputSecretPath, + inputSecretAlias) < 0) + goto error; + } + if (convertStep != VIR_STORAGE_VOL_ENCRYPT_CONVERT) { if (storageBackendCreateQemuImgSetOptions(cmd, encinfo, info) < 0) goto error; @@ -1163,20 +1186,33 @@ virStorageBackendCreateQemuImgCmdFromVol(virStoragePoolObjPtr pool, virCommandAddArgFormat(cmd, "%lluK", info.size_arg); } else { /* source */ - virCommandAddArgFormat(cmd, "driver=%s,file.filename=%s", - info.inputType ? info.inputType : "raw", - info.inputPath); + if (inputenc) + virCommandAddArgFormat(cmd, + "driver=luks,file.filename=%s,key-secret=%s", + info.inputPath, inputSecretAlias); + else + virCommandAddArgFormat(cmd, "driver=%s,file.filename=%s", + info.inputType ? info.inputType : "raw", + info.inputPath); /* dest */ - virCommandAddArgFormat(cmd, "driver=%s,file.filename=%s,key-secret=%s", - info.type, info.path, info.secretAlias); + if (enc) + virCommandAddArgFormat(cmd, + "driver=%s,file.filename=%s,key-secret=%s", + info.type, info.path, info.secretAlias); + else + virCommandAddArgFormat(cmd, "driver=%s,file.filename=%s", + info.type, info.path); + } VIR_FREE(info.secretAlias); + VIR_FREE(inputSecretAlias); return cmd; error: VIR_FREE(info.secretAlias); + VIR_FREE(inputSecretAlias); virCommandFree(cmd); return NULL; } @@ -1262,6 +1298,7 @@ storageBackendDoCreateQemuImg(virStoragePoolObjPtr pool, unsigned int flags, const char *create_tool, const char *secretPath, + const char *inputSecretPath, virStorageVolEncryptConvertStep convertStep) { int ret; @@ -1269,7 +1306,8 @@ storageBackendDoCreateQemuImg(virStoragePoolObjPtr pool, cmd = virStorageBackendCreateQemuImgCmdFromVol(pool, vol, inputvol, flags, create_tool, - secretPath, convertStep); + secretPath, inputSecretPath, + convertStep); if (!cmd) return -1; @@ -1290,6 +1328,7 @@ storageBackendCreateQemuImg(virStoragePoolObjPtr pool, int ret = -1; char *create_tool; char *secretPath = NULL; + char *inputSecretPath = NULL; virStorageVolEncryptConvertStep convertStep = VIR_STORAGE_VOL_ENCRYPT_NONE; virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA, -1); @@ -1306,16 +1345,21 @@ storageBackendCreateQemuImg(virStoragePoolObjPtr pool, !(secretPath = storageBackendCreateQemuImgSecretPath(pool, vol))) goto cleanup; + if (inputvol && inputvol->target.encryption && + !(inputSecretPath = storageBackendCreateQemuImgSecretPath(pool, + inputvol))) + goto cleanup; + /* Using an input file for encryption requires a multi-step process * to create an image of the same size as the inputvol and then to * convert the inputvol afterwards. */ - if (secretPath && inputvol) + if ((secretPath || inputSecretPath) && inputvol) convertStep = VIR_STORAGE_VOL_ENCRYPT_CREATE; do { ret = storageBackendDoCreateQemuImg(pool, vol, inputvol, flags, create_tool, secretPath, - convertStep); + inputSecretPath, convertStep); /* Failure to convert, attempt to delete what we created */ if (ret < 0 && convertStep == VIR_STORAGE_VOL_ENCRYPT_CONVERT) @@ -1337,6 +1381,10 @@ storageBackendCreateQemuImg(virStoragePoolObjPtr pool, unlink(secretPath); VIR_FREE(secretPath); } + if (inputSecretPath) { + unlink(inputSecretPath); + VIR_FREE(inputSecretPath); + } VIR_FREE(create_tool); return ret; } diff --git a/src/storage/storage_util.h b/src/storage/storage_util.h index 6fc8e8972c..58b991c772 100644 --- a/src/storage/storage_util.h +++ b/src/storage/storage_util.h @@ -167,6 +167,7 @@ virStorageBackendCreateQemuImgCmdFromVol(virStoragePoolObjPtr pool, unsigned int flags, const char *create_tool, const char *secretPath, + const char *inputSecretPath, virStorageVolEncryptConvertStep convertStep); int virStorageBackendSCSIFindLUs(virStoragePoolObjPtr pool, diff --git a/tests/storagevolxml2argvdata/luks-convert-encrypt.argv b/tests/storagevolxml2argvdata/luks-convert-encrypt.argv new file mode 100644 index 0000000000..b2ad16b7cb --- /dev/null +++ b/tests/storagevolxml2argvdata/luks-convert-encrypt.argv @@ -0,0 +1,11 @@ +qemu-img create -f luks \ +--object secret,id=encrypt2.img_encrypt0,file=/path/to/secretFile \ +-o key-secret=encrypt2.img_encrypt0 \ +/var/lib/libvirt/images/encrypt2.img 5242880K +qemu-img convert --image-opts -n --target-image-opts \ +--object secret,id=encrypt2.img_encrypt0,file=/path/to/secretFile \ +--object secret,id=encrypt1.img_encrypt0,file=/path/to/inputSecretFile \ +driver=luks,file.filename=/var/lib/libvirt/images/encrypt1.img,\ +key-secret=encrypt1.img_encrypt0 \ +driver=luks,file.filename=/var/lib/libvirt/images/encrypt2.img,\ +key-secret=encrypt2.img_encrypt0 diff --git a/tests/storagevolxml2argvdata/luks-convert-encrypt2fileqcow2.argv b/tests/storagevolxml2argvdata/luks-convert-encrypt2fileqcow2.argv new file mode 100644 index 0000000000..82cb364b61 --- /dev/null +++ b/tests/storagevolxml2argvdata/luks-convert-encrypt2fileqcow2.argv @@ -0,0 +1,7 @@ +qemu-img create -f qcow2 \ +-o compat=0.10 /var/lib/libvirt/images/sparse-qcow2.img 1073741824K +qemu-img convert --image-opts -n --target-image-opts \ +--object secret,id=encrypt2.img_encrypt0,file=/path/to/inputSecretFile \ +driver=luks,file.filename=/var/lib/libvirt/images/encrypt2.img,\ +key-secret=encrypt2.img_encrypt0 \ +driver=qcow2,file.filename=/var/lib/libvirt/images/sparse-qcow2.img diff --git a/tests/storagevolxml2argvdata/luks-convert-encrypt2fileraw.argv b/tests/storagevolxml2argvdata/luks-convert-encrypt2fileraw.argv new file mode 100644 index 0000000000..2661c345a8 --- /dev/null +++ b/tests/storagevolxml2argvdata/luks-convert-encrypt2fileraw.argv @@ -0,0 +1,7 @@ +qemu-img create -f raw \ +/var/lib/libvirt/images/sparse.img 1073741824K +qemu-img convert --image-opts -n --target-image-opts \ +--object secret,id=encrypt2.img_encrypt0,file=/path/to/inputSecretFile \ +driver=luks,file.filename=/var/lib/libvirt/images/encrypt2.img,\ +key-secret=encrypt2.img_encrypt0 \ +driver=raw,file.filename=/var/lib/libvirt/images/sparse.img diff --git a/tests/storagevolxml2argvtest.c b/tests/storagevolxml2argvtest.c index 6a9a080dd1..105705f348 100644 --- a/tests/storagevolxml2argvtest.c +++ b/tests/storagevolxml2argvtest.c @@ -85,7 +85,7 @@ testCompareXMLToArgvFiles(bool shouldFail, * convert the inputvol afterwards. Since we only care about the * command line we have to copy code from storageBackendCreateQemuImg * and adjust it for the test needs. */ - if (inputvol && vol->target.encryption) + if (inputvol && (vol->target.encryption || inputvol->target.encryption)) convertStep = VIR_STORAGE_VOL_ENCRYPT_CREATE; do { @@ -93,6 +93,7 @@ testCompareXMLToArgvFiles(bool shouldFail, inputvol, flags, create_tool, "/path/to/secretFile", + "/path/to/inputSecretFile", convertStep); if (!cmd) { if (shouldFail) { @@ -288,6 +289,18 @@ mymain(void) "pool-dir", "vol-file-qcow2", "luks-convert-qcow2", 0); + DO_TEST("pool-dir", "vol-encrypt2", + "pool-dir", "vol-encrypt1", + "luks-convert-encrypt", 0); + + DO_TEST("pool-dir", "vol-file", + "pool-dir", "vol-encrypt2", + "luks-convert-encrypt2fileraw", 0); + + DO_TEST("pool-dir", "vol-file-qcow2", + "pool-dir", "vol-encrypt2", + "luks-convert-encrypt2fileqcow2", 0); + return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; } diff --git a/tests/storagevolxml2xmlin/vol-encrypt1.xml b/tests/storagevolxml2xmlin/vol-encrypt1.xml new file mode 100644 index 0000000000..681734dc7b --- /dev/null +++ b/tests/storagevolxml2xmlin/vol-encrypt1.xml @@ -0,0 +1,21 @@ + + encrypt1.img + /var/lib/libvirt/images/encrypt1.img + + + 5 + 294912 + + /var/lib/libvirt/images/encrypt1.img + + + 0644 + 0 + 0 + + + + + + + diff --git a/tests/storagevolxml2xmlin/vol-encrypt2.xml b/tests/storagevolxml2xmlin/vol-encrypt2.xml new file mode 100644 index 0000000000..0507d3b9e6 --- /dev/null +++ b/tests/storagevolxml2xmlin/vol-encrypt2.xml @@ -0,0 +1,21 @@ + + encrypt2.img + /var/lib/libvirt/images/encrypt2.img + + + 5 + 294912 + + /var/lib/libvirt/images/encrypt2.img + + + 0644 + 0 + 0 + + + + + + +