[libvirt] [PATCH 4/9] Add support for encrypted (qcow) volume creation.

Daniel P. Berrange berrange at redhat.com
Thu Jul 23 20:36:13 UTC 2009


On Tue, Jul 21, 2009 at 01:12:00PM +0200, Miloslav Trma?? wrote:
> Supports only virStorageVolCreateXML, not virStorageVolCreateXMLFrom.
> 
> Curiously, qemu-img does not need the passphrase for anything to create
> an encrypted volume.  This implementation is sufficient for the qcow2
> format, and for other formats when all encryption parameters are
> pre-specified.
> 
> The qcow2 passphrase is stored in libvirt only during the volume
> creation operation, and automatically deleted afterwards.  Other users
> might be able to query the volume properties while the volume is being
> created, but virStorageVolGetXMLDesc() won't reveal the passphrase to
> them.
> 
> An earlier patch description has mentioned the possibility of a libvirt
> user specifying only the encryption format (or not even the format),
> letting libvirt to choose the parameters and return them.  This would
> require libvirt interface extensions, and it is not supported by this
> patch.
> ---
>  src/storage_backend.c         |   41 +++++++++++++++++++++++++++++++++++++++--
>  src/storage_backend_disk.c    |    7 +++++++
>  src/storage_backend_fs.c      |    7 +++++++
>  src/storage_backend_logical.c |    7 +++++++
>  src/storage_driver.c          |    4 ++++
>  5 files changed, 64 insertions(+), 2 deletions(-)
> 
> diff --git a/src/storage_backend.c b/src/storage_backend.c
> index 1664804..42c59ad 100644
> --- a/src/storage_backend.c
> +++ b/src/storage_backend.c
> @@ -246,6 +246,13 @@ virStorageBackendCreateRaw(virConnectPtr conn,
>      unsigned long long remain;
>      char *buf = NULL;
>  
> +    if (vol->encryption != NULL) {
> +        virStorageReportError(conn, VIR_ERR_NO_SUPPORT,
> +                              "%s", _("storage pool does not support encrypted "
> +                                      "volumes"));
> +        return -1;
> +    }
> +
>      if ((fd = open(vol->target.path, O_RDWR | O_CREAT | O_EXCL,
>                     vol->target.perms.mode)) < 0) {
>          virReportSystemError(conn, errno,
> @@ -346,15 +353,17 @@ virStorageBackendCreateQemuImg(virConnectPtr conn,
>                              NULL;
>  
>      const char **imgargv;
> +    /* The extra NULL field is for indicating encryption (-e). */
>      const char *imgargvnormal[] = {
>          NULL, "create",
>          "-f", type,
>          vol->target.path,
>          size,
>          NULL,
> +        NULL
>      };
>      /* Extra NULL fields are for including "backingType" when using
> -     * kvm-img. It's -F backingType
> +     * kvm-img (-F backingType), and for indicating encryption (-e).
>       */
>      const char *imgargvbacking[] = {
>          NULL, "create",
> @@ -364,6 +373,7 @@ virStorageBackendCreateQemuImg(virConnectPtr conn,
>          size,
>          NULL,
>          NULL,
> +        NULL,
>          NULL
>      };
>      const char *convargv[] = {
> @@ -417,6 +427,22 @@ virStorageBackendCreateQemuImg(virConnectPtr conn,
>          }
>      }
>  
> +    if (vol->encryption != NULL) {
> +        if (vol->encryption->format != VIR_STORAGE_ENCRYPTION_FORMAT_QCOW) {
> +            virStorageReportError(conn, VIR_ERR_NO_SUPPORT,
> +                                  _("unsupported volume encryption format %d"),
> +                                  vol->encryption->format);
> +            return -1;
> +        }
> +        if (vol->target.format != VIR_STORAGE_VOL_FILE_QCOW &&
> +            vol->target.format != VIR_STORAGE_VOL_FILE_QCOW2) {
> +            virStorageReportError(conn, VIR_ERR_NO_SUPPORT,
> +                                  _("qcow volume encryption unsupported with "
> +                                    "volume format %s"), type);
> +            return -1;
> +        }
> +    }
> +
>      if ((create_tool = virFindFileInPath("kvm-img")) != NULL)
>          use_kvmimg = 1;
>      else if ((create_tool = virFindFileInPath("qemu-img")) != NULL)
> @@ -437,11 +463,16 @@ virStorageBackendCreateQemuImg(virConnectPtr conn,
>              imgargvbacking[7] = backingType;
>              imgargvbacking[8] = vol->target.path;
>              imgargvbacking[9] = size;
> -        }
> +            if (vol->encryption != NULL)
> +                imgargvbacking[10] = "-e";
> +        } else if (vol->encryption != NULL)
> +            imgargvbacking[8] = "-e";
>          imgargv = imgargvbacking;
>      } else {
>          imgargvnormal[0] = create_tool;
>          imgargv = imgargvnormal;
> +        if (vol->encryption != NULL)
> +            imgargv[6] = "-e";
>      }
>  
>  
> @@ -490,6 +521,12 @@ virStorageBackendCreateQcowCreate(virConnectPtr conn,
>                                "qcow-create"));
>          return -1;
>      }
> +    if (vol->encryption != NULL) {
> +        virStorageReportError(conn, VIR_ERR_NO_SUPPORT,
> +                              "%s", _("encrypted volumes not supported with "
> +                                      "qcow-create"));
> +        return -1;
> +    }
>  
>      /* Size in MB - yes different units to qemu-img :-( */
>      snprintf(size, sizeof(size), "%llu", vol->capacity/1024/1024);
> diff --git a/src/storage_backend_disk.c b/src/storage_backend_disk.c
> index ae2acae..8f4f0ed 100644
> --- a/src/storage_backend_disk.c
> +++ b/src/storage_backend_disk.c
> @@ -557,6 +557,13 @@ virStorageBackendDiskCreateVol(virConnectPtr conn,
>          NULL
>      };
>  
> +    if (vol->encryption != NULL) {
> +        virStorageReportError(conn, VIR_ERR_NO_SUPPORT,
> +                              "%s", _("storage pool does not support encrypted "
> +                                      "volumes"));
> +        return -1;
> +    }
> +
>      if (virStorageBackendDiskPartFormat(conn, pool, vol, partFormat) != 0) {
>          return -1;
>      }
> diff --git a/src/storage_backend_fs.c b/src/storage_backend_fs.c
> index 0219eb6..b43daef 100644
> --- a/src/storage_backend_fs.c
> +++ b/src/storage_backend_fs.c
> @@ -1070,6 +1070,13 @@ _virStorageBackendFileSystemVolBuild(virConnectPtr conn,
>      int tool_type;
>  
>      if (inputvol) {
> +        if (vol->encryption != NULL) {
> +            virStorageReportError(conn, VIR_ERR_NO_SUPPORT,
> +                                  "%s", _("storage pool does not support "
> +                                          "building encrypted volumes from "
> +                                          "other volumes"));
> +            return -1;
> +        }
>          create_func = virStorageBackendGetBuildVolFromFunction(conn, vol,
>                                                                 inputvol);
>          if (!create_func)
> diff --git a/src/storage_backend_logical.c b/src/storage_backend_logical.c
> index 6c123ae..822d321 100644
> --- a/src/storage_backend_logical.c
> +++ b/src/storage_backend_logical.c
> @@ -581,6 +581,13 @@ virStorageBackendLogicalCreateVol(virConnectPtr conn,
>      };
>      const char **cmdargv = cmdargvnew;
>  
> +    if (vol->encryption != NULL) {
> +        virStorageReportError(conn, VIR_ERR_NO_SUPPORT,
> +                              "%s", _("storage pool does not support encrypted "
> +                                      "volumes"));
> +        return -1;
> +    }
> +
>      if (vol->backingStore.path) {
>          cmdargv = cmdargvsnap;
>      }
> diff --git a/src/storage_driver.c b/src/storage_driver.c
> index e9ecb20..98db9a0 100644
> --- a/src/storage_driver.c
> +++ b/src/storage_driver.c
> @@ -1305,6 +1305,8 @@ storageVolumeCreateXML(virStoragePoolPtr obj,
>  cleanup:
>      if (volobj)
>          virUnrefStorageVol(volobj);
> +    if (voldef)
> +        virStorageEncryptionDropSecrets(voldef->encryption);
>      virStorageVolDefFree(voldef);
>      if (pool)
>          virStoragePoolObjUnlock(pool);
> @@ -1466,6 +1468,8 @@ storageVolumeCreateXMLFrom(virStoragePoolPtr obj,
>  cleanup:
>      if (volobj)
>          virUnrefStorageVol(volobj);
> +    if (newvol)
> +        virStorageEncryptionDropSecrets(newvol->encryption);
>      virStorageVolDefFree(newvol);
>      if (pool)
>          virStoragePoolObjUnlock(pool);

As per other mails, I don't think its neccessary to drop the secrets
from volumes here. At least not until we introduce keystores as an
explicit public API

Daniel
-- 
|: Red Hat, Engineering, London   -o-   http://people.redhat.com/berrange/ :|
|: http://libvirt.org  -o-  http://virt-manager.org  -o-  http://ovirt.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505  -o-  F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|




More information about the libvir-list mailing list