Re: [libvirt] [PATCH 17/19] storage: Add support to create a luks volume
On 06/21/2016 09:53 AM, Peter Krempa wrote: > On Mon, Jun 13, 2016 at 20:27:56 -0400, John Ferlan wrote: >> If the volume xml was looking to create a luks volume take the necessary >> steps in order to make that happen. >> >> The processing will be: >> 1. create a temporary file in the storage pool target path >>1a. the file name will either be $volname_$UUID.tmp or $volname_$USAGE.tmp >>depending on how the encryption xml specified fetching the secret >>1b. create/open the file, initially setting mode to 0600 with current >>effective uid:gid as owner >>1c. fetch the secret into a buffer and write that into the file >>1d. change file protections to 0400 >> >> 2. create a secret object >>2a. use a similarly crafted alias to the file name >>2b. add the file to the object >> >> 3. create/add luks options to the commandline >>3a. at the very least a "key-secret" using the secret object alias >>3b. if found in the XML the various "cipher" and "ivgen" options >> >> Signed-off-by: John Ferlan>> --- >> src/libvirt_private.syms | 1 + >> src/storage/storage_backend.c | 285 >> ++--- >> src/storage/storage_backend.h | 3 +- >> src/util/virqemu.c | 23 >> src/util/virqemu.h | 6 + >> tests/storagevolxml2argvtest.c | 3 +- >> 6 files changed, 300 insertions(+), 21 deletions(-) >> [...] >> + >> static int >> virStorageBackendQEMUImgBackingFormat(const char *qemuimg) >> { >> @@ -915,12 +940,18 @@ virStorageBackendQEMUImgBackingFormat(const char >> *qemuimg) >> * out what else we have */ >> int ret = QEMU_IMG_BACKING_FORMAT_OPTIONS; >> >> -/* QEMU 2.0 changed to using a format that only QEMU 1.1 and newer >> - * understands. Since we still support QEMU 0.12 and newer, we need >> - * to be able to handle the previous format as can be set via a >> - * compat=0.10 option. */ >> -if (virStorageBackendQemuImgSupportsCompat(qemuimg)) >> -ret = QEMU_IMG_BACKING_FORMAT_OPTIONS_COMPAT; >> +/* QEMU 2.6 added support for luks - let's check for that. >> + * If available, then we can also assume OPTIONS_COMPAT is present */ >> +if (virStorageBackendQemuImgSupportsLuks(qemuimg)) { >> +ret = QEMU_IMG_FORMAT_LUKS; >> +} else { >> +/* QEMU 2.0 changed to using a format that only QEMU 1.1 and newer >> + * understands. Since we still support QEMU 0.12 and newer, we need >> + * to be able to handle the previous format as can be set via a >> + * compat=0.10 option. */ >> +if (virStorageBackendQemuImgSupportsCompat(qemuimg)) >> +ret = QEMU_IMG_BACKING_FORMAT_OPTIONS_COMPAT; >> +} > > This looks like it's becoming a source of technical debt. Heaps of > comments aren't helping. > It's on the short list of things to deal with. >> >> return ret; >> } >> @@ -941,21 +972,31 @@ struct _virStorageBackendQemuImgInfo { >> const char *inputPath; >> const char *inputFormatStr; >> int inputFormat; >> + >> +char *secretAlias; >> +const char *secretPath; >> }; >> [...] >> >> +/* Create a hopefully unique enough name to be used for both the >> + * secretPath and secretAlias generation > > This won't fly. There's only one way to guarantee that there won't be a > collision. You need to create a file in a private path. > >> + */ >> +static char * >> +virStorageBackendCreateQemuImgLuksName(const char *volname, >> + virStorageEncryptionPtr enc) >> +{ >> +char *ret; >> + >> +if (enc->secrets[0]->secdef.type == VIR_SECRET_LOOKUP_TYPE_UUID) >> +ignore_value(virAsprintf(, "%s_%s", volname, >> + enc->secrets[0]->secdef.u.uuid)); >> +else >> +ignore_value(virAsprintf(, "%s_%s", volname, >> + enc->secrets[0]->secdef.u.usage)); > > usage is user provided text. Also your example in previous patch uses > slashes in it. I don't think it will end up well in this case. > Ugh... right. I'm almost tempted to avoid a file type of secret and make it be an AES type secret. This goes away anyway. >> +return ret; >> +} >> + [...] >> +static char * >> +virStorageBackendCreateQemuImgSecretPath(virConnectPtr conn, >> + virStoragePoolObjPtr pool, >> + virStorageVolDefPtr vol) >> +{ >> +virStorageEncryptionPtr enc = vol->target.encryption; >> +char *str = NULL; >> +char *secretPath = NULL; >> +int fd = -1; >> +uint8_t *secret = NULL; >> +size_t secretlen = 0; >> + >> +if (!enc) { >> +virReportError(VIR_ERR_INTERNAL_ERROR, "%s", >> + _("missing encryption description")); >> +return NULL; >> +} >> + >> +if (!conn || !conn->secretDriver || >> +
Re: [libvirt] [PATCH 17/19] storage: Add support to create a luks volume
On Mon, Jun 13, 2016 at 20:27:56 -0400, John Ferlan wrote: > If the volume xml was looking to create a luks volume take the necessary > steps in order to make that happen. > > The processing will be: > 1. create a temporary file in the storage pool target path >1a. the file name will either be $volname_$UUID.tmp or $volname_$USAGE.tmp >depending on how the encryption xml specified fetching the secret >1b. create/open the file, initially setting mode to 0600 with current >effective uid:gid as owner >1c. fetch the secret into a buffer and write that into the file >1d. change file protections to 0400 > > 2. create a secret object >2a. use a similarly crafted alias to the file name >2b. add the file to the object > > 3. create/add luks options to the commandline >3a. at the very least a "key-secret" using the secret object alias >3b. if found in the XML the various "cipher" and "ivgen" options > > Signed-off-by: John Ferlan> --- > src/libvirt_private.syms | 1 + > src/storage/storage_backend.c | 285 > ++--- > src/storage/storage_backend.h | 3 +- > src/util/virqemu.c | 23 > src/util/virqemu.h | 6 + > tests/storagevolxml2argvtest.c | 3 +- > 6 files changed, 300 insertions(+), 21 deletions(-) > > diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms > index fdf06ae..0d6d080 100644 > --- a/src/libvirt_private.syms > +++ b/src/libvirt_private.syms > @@ -2153,6 +2153,7 @@ virProcessWait; > > > # util/virqemu.h > +virQEMUBuildLuksOpts; > virQEMUBuildObjectCommandlineFromJSON; > > > diff --git a/src/storage/storage_backend.c b/src/storage/storage_backend.c > index 4965c9e..fc50807 100644 > --- a/src/storage/storage_backend.c > +++ b/src/storage/storage_backend.c > @@ -55,11 +55,14 @@ > #include "viralloc.h" > #include "internal.h" > #include "secret_conf.h" > +#include "secret_util.h" > #include "viruuid.h" > #include "virstoragefile.h" > #include "storage_backend.h" > #include "virlog.h" > #include "virfile.h" > +#include "virjson.h" > +#include "virqemu.h" > #include "stat-time.h" > #include "virstring.h" > #include "virxml.h" > @@ -880,6 +883,7 @@ virStoragePloopResize(virStorageVolDefPtr vol, > enum { > QEMU_IMG_BACKING_FORMAT_OPTIONS = 0, > QEMU_IMG_BACKING_FORMAT_OPTIONS_COMPAT, > +QEMU_IMG_FORMAT_LUKS, > }; > > static bool > @@ -907,6 +911,27 @@ virStorageBackendQemuImgSupportsCompat(const char > *qemuimg) > return ret; > } > > + > +static bool > +virStorageBackendQemuImgSupportsLuks(const char *qemuimg) > +{ > +bool ret = false; > +int exitstatus = -1; > +virCommandPtr cmd = virCommandNewArgList(qemuimg, "create", "-o", "?", > + "-f", "luks", "/dev/null", > NULL); > + > +if (virCommandRun(cmd, ) < 0) > +goto cleanup; > + > +if (exitstatus == 0) > +ret = true; > + > + cleanup: > +virCommandFree(cmd); > +return ret; > +} > + > + > static int > virStorageBackendQEMUImgBackingFormat(const char *qemuimg) > { > @@ -915,12 +940,18 @@ virStorageBackendQEMUImgBackingFormat(const char > *qemuimg) > * out what else we have */ > int ret = QEMU_IMG_BACKING_FORMAT_OPTIONS; > > -/* QEMU 2.0 changed to using a format that only QEMU 1.1 and newer > - * understands. Since we still support QEMU 0.12 and newer, we need > - * to be able to handle the previous format as can be set via a > - * compat=0.10 option. */ > -if (virStorageBackendQemuImgSupportsCompat(qemuimg)) > -ret = QEMU_IMG_BACKING_FORMAT_OPTIONS_COMPAT; > +/* QEMU 2.6 added support for luks - let's check for that. > + * If available, then we can also assume OPTIONS_COMPAT is present */ > +if (virStorageBackendQemuImgSupportsLuks(qemuimg)) { > +ret = QEMU_IMG_FORMAT_LUKS; > +} else { > +/* QEMU 2.0 changed to using a format that only QEMU 1.1 and newer > + * understands. Since we still support QEMU 0.12 and newer, we need > + * to be able to handle the previous format as can be set via a > + * compat=0.10 option. */ > +if (virStorageBackendQemuImgSupportsCompat(qemuimg)) > +ret = QEMU_IMG_BACKING_FORMAT_OPTIONS_COMPAT; > +} This looks like it's becoming a source of technical debt. Heaps of comments aren't helping. > > return ret; > } > @@ -941,21 +972,31 @@ struct _virStorageBackendQemuImgInfo { > const char *inputPath; > const char *inputFormatStr; > int inputFormat; > + > +char *secretAlias; > +const char *secretPath; > }; > > + > static int > -virStorageBackendCreateQemuImgOpts(char **opts, > +virStorageBackendCreateQemuImgOpts(virStorageEncryptionPtr enc, > + char **opts, > struct _virStorageBackendQemuImgInfo info) > { >
[libvirt] [PATCH 17/19] storage: Add support to create a luks volume
If the volume xml was looking to create a luks volume take the necessary steps in order to make that happen. The processing will be: 1. create a temporary file in the storage pool target path 1a. the file name will either be $volname_$UUID.tmp or $volname_$USAGE.tmp depending on how the encryption xml specified fetching the secret 1b. create/open the file, initially setting mode to 0600 with current effective uid:gid as owner 1c. fetch the secret into a buffer and write that into the file 1d. change file protections to 0400 2. create a secret object 2a. use a similarly crafted alias to the file name 2b. add the file to the object 3. create/add luks options to the commandline 3a. at the very least a "key-secret" using the secret object alias 3b. if found in the XML the various "cipher" and "ivgen" options Signed-off-by: John Ferlan--- src/libvirt_private.syms | 1 + src/storage/storage_backend.c | 285 ++--- src/storage/storage_backend.h | 3 +- src/util/virqemu.c | 23 src/util/virqemu.h | 6 + tests/storagevolxml2argvtest.c | 3 +- 6 files changed, 300 insertions(+), 21 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index fdf06ae..0d6d080 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2153,6 +2153,7 @@ virProcessWait; # util/virqemu.h +virQEMUBuildLuksOpts; virQEMUBuildObjectCommandlineFromJSON; diff --git a/src/storage/storage_backend.c b/src/storage/storage_backend.c index 4965c9e..fc50807 100644 --- a/src/storage/storage_backend.c +++ b/src/storage/storage_backend.c @@ -55,11 +55,14 @@ #include "viralloc.h" #include "internal.h" #include "secret_conf.h" +#include "secret_util.h" #include "viruuid.h" #include "virstoragefile.h" #include "storage_backend.h" #include "virlog.h" #include "virfile.h" +#include "virjson.h" +#include "virqemu.h" #include "stat-time.h" #include "virstring.h" #include "virxml.h" @@ -880,6 +883,7 @@ virStoragePloopResize(virStorageVolDefPtr vol, enum { QEMU_IMG_BACKING_FORMAT_OPTIONS = 0, QEMU_IMG_BACKING_FORMAT_OPTIONS_COMPAT, +QEMU_IMG_FORMAT_LUKS, }; static bool @@ -907,6 +911,27 @@ virStorageBackendQemuImgSupportsCompat(const char *qemuimg) return ret; } + +static bool +virStorageBackendQemuImgSupportsLuks(const char *qemuimg) +{ +bool ret = false; +int exitstatus = -1; +virCommandPtr cmd = virCommandNewArgList(qemuimg, "create", "-o", "?", + "-f", "luks", "/dev/null", NULL); + +if (virCommandRun(cmd, ) < 0) +goto cleanup; + +if (exitstatus == 0) +ret = true; + + cleanup: +virCommandFree(cmd); +return ret; +} + + static int virStorageBackendQEMUImgBackingFormat(const char *qemuimg) { @@ -915,12 +940,18 @@ virStorageBackendQEMUImgBackingFormat(const char *qemuimg) * out what else we have */ int ret = QEMU_IMG_BACKING_FORMAT_OPTIONS; -/* QEMU 2.0 changed to using a format that only QEMU 1.1 and newer - * understands. Since we still support QEMU 0.12 and newer, we need - * to be able to handle the previous format as can be set via a - * compat=0.10 option. */ -if (virStorageBackendQemuImgSupportsCompat(qemuimg)) -ret = QEMU_IMG_BACKING_FORMAT_OPTIONS_COMPAT; +/* QEMU 2.6 added support for luks - let's check for that. + * If available, then we can also assume OPTIONS_COMPAT is present */ +if (virStorageBackendQemuImgSupportsLuks(qemuimg)) { +ret = QEMU_IMG_FORMAT_LUKS; +} else { +/* QEMU 2.0 changed to using a format that only QEMU 1.1 and newer + * understands. Since we still support QEMU 0.12 and newer, we need + * to be able to handle the previous format as can be set via a + * compat=0.10 option. */ +if (virStorageBackendQemuImgSupportsCompat(qemuimg)) +ret = QEMU_IMG_BACKING_FORMAT_OPTIONS_COMPAT; +} return ret; } @@ -941,21 +972,31 @@ struct _virStorageBackendQemuImgInfo { const char *inputPath; const char *inputFormatStr; int inputFormat; + +char *secretAlias; +const char *secretPath; }; + static int -virStorageBackendCreateQemuImgOpts(char **opts, +virStorageBackendCreateQemuImgOpts(virStorageEncryptionPtr enc, + char **opts, struct _virStorageBackendQemuImgInfo info) { virBuffer buf = VIR_BUFFER_INITIALIZER; -if (info.backingPath) -virBufferAsprintf(, "backing_fmt=%s,", - virStorageFileFormatTypeToString(info.backingFormat)); -if (info.encryption) -virBufferAddLit(, "encryption=on,"); -if (info.preallocate) -virBufferAddLit(, "preallocation=metadata,"); +if (info.format == VIR_STORAGE_FILE_LUKS) { +virQEMUBuildLuksOpts(, enc,