diff --git a/docs/format.html b/docs/format.html index 3c20b5fbc2..e8b14983fe 100644 --- a/docs/format.html +++ b/docs/format.html @@ -62,6 +62,10 @@
Storage
+
  • +
    + Storage Encryption +
  • Capabilities diff --git a/docs/formatcaps.html b/docs/formatcaps.html index 5f2bc72723..32401016db 100644 --- a/docs/formatcaps.html +++ b/docs/formatcaps.html @@ -62,6 +62,10 @@
    Storage
    +
  • +
    + Storage Encryption +
  • Capabilities diff --git a/docs/formatdomain.html b/docs/formatdomain.html index 6b655ad443..efba65a3f1 100644 --- a/docs/formatdomain.html +++ b/docs/formatdomain.html @@ -62,6 +62,10 @@
    Storage
    +
  • +
    + Storage Encryption +
  • Capabilities diff --git a/docs/formatnetwork.html b/docs/formatnetwork.html index 72a3cda3c6..845e55855e 100644 --- a/docs/formatnetwork.html +++ b/docs/formatnetwork.html @@ -62,6 +62,10 @@
    Storage
    +
  • +
    + Storage Encryption +
  • Capabilities diff --git a/docs/formatnode.html b/docs/formatnode.html index 516c27b12c..b269baa0d7 100644 --- a/docs/formatnode.html +++ b/docs/formatnode.html @@ -62,6 +62,10 @@
    Storage
    +
  • +
    + Storage Encryption +
  • Capabilities diff --git a/docs/formatsecret.html b/docs/formatsecret.html index 998e874d05..929eb86e54 100644 --- a/docs/formatsecret.html +++ b/docs/formatsecret.html @@ -62,6 +62,10 @@
    Storage
    +
  • +
    + Storage Encryption +
  • Capabilities diff --git a/docs/formatstorage.html b/docs/formatstorage.html index 02cbcaca1c..8c16a0fb75 100644 --- a/docs/formatstorage.html +++ b/docs/formatstorage.html @@ -62,6 +62,10 @@
    Storage
    +
  • +
    + Storage Encryption +
  • Capabilities diff --git a/docs/formatstorageencryption.html b/docs/formatstorageencryption.html new file mode 100644 index 0000000000..15175fe5fb --- /dev/null +++ b/docs/formatstorageencryption.html @@ -0,0 +1,209 @@ + + + + + + + + + libvirt: Storage volume encryption XML format + + + + +
    + +
    +

    Storage volume encryption XML format

    + +

    + Storage volume encryption XML +

    +

    + Storage volumes may be encrypted, the XML snippet described below is used + to represent the details of the encryption. It can be used as a part + of a domain or storage configuration. +

    +

    + The top-level tag of volume encryption specification + is encryption, with a mandatory + attribute format. Currently defined values + of format are default and qcow. + Each value of format implies some expectations about the + content of the encryption tag. Other format values may be + defined in the future. +

    +

    + The encryption tag can currently contain a sequence of + secret tags, each with mandatory attributes type + and uuid. The only currently defined value of + type is passphrase. uuid + refers to a secret known to libvirt. libvirt can use a secret value + previously set using virSecretSetValue(), or, if supported + by the particular volume format and driver, automatically generate a + secret value at the time of volume creation, and store it using the + specified uuid. +

    +

    +

    +

    + "default" format +

    +

    + <encryption type="default"/> can be specified only + when creating a volume. If the volume is successfully created, the + encryption formats, parameters and secrets will be auto-generated by + libvirt and the attached encryption tag will be updated. + The unmodified contents of the encryption tag can be used + in later operations with the volume, or when setting up a domain that + uses the volume. +

    +

    + "qcow" format +

    +

    + The qcow format specifies that the built-in encryption + support in qcow- or qcow2-formatted volume + images should be used. A single + <secret type='passphrase'> element is expected. If + the secret element is not present during volume creation, + a secret is automatically generated and attached to the volume. +

    +

    + Example +

    +

    + Here is a simple example, specifying use of the qcow format: +

    +
    +      <encryption format='qcow'>
    +         <secret type='passphrase' uuid='c1f11a6d-8c5d-4a3e-ac7a-4e171c5e0d4a' />
    +      </encryption>
    +
    +
    + + + diff --git a/docs/formatstorageencryption.html.in b/docs/formatstorageencryption.html.in new file mode 100644 index 0000000000..0e5dcee96b --- /dev/null +++ b/docs/formatstorageencryption.html.in @@ -0,0 +1,65 @@ + + +

    Storage volume encryption XML format

    + + + +

    Storage volume encryption XML

    + +

    + Storage volumes may be encrypted, the XML snippet described below is used + to represent the details of the encryption. It can be used as a part + of a domain or storage configuration. +

    +

    + The top-level tag of volume encryption specification + is encryption, with a mandatory + attribute format. Currently defined values + of format are default and qcow. + Each value of format implies some expectations about the + content of the encryption tag. Other format values may be + defined in the future. +

    +

    + The encryption tag can currently contain a sequence of + secret tags, each with mandatory attributes type + and uuid. The only currently defined value of + type is passphrase. uuid + refers to a secret known to libvirt. libvirt can use a secret value + previously set using virSecretSetValue(), or, if supported + by the particular volume format and driver, automatically generate a + secret value at the time of volume creation, and store it using the + specified uuid. +

    +

    "default" format

    +

    + <encryption type="default"/> can be specified only + when creating a volume. If the volume is successfully created, the + encryption formats, parameters and secrets will be auto-generated by + libvirt and the attached encryption tag will be updated. + The unmodified contents of the encryption tag can be used + in later operations with the volume, or when setting up a domain that + uses the volume. +

    +

    "qcow" format

    +

    + The qcow format specifies that the built-in encryption + support in qcow- or qcow2-formatted volume + images should be used. A single + <secret type='passphrase'> element is expected. If + the secret element is not present during volume creation, + a secret is automatically generated and attached to the volume. +

    + +

    Example

    + +

    + Here is a simple example, specifying use of the qcow format: +

    + +
    +      <encryption format='qcow'>
    +         <secret type='passphrase' uuid='c1f11a6d-8c5d-4a3e-ac7a-4e171c5e0d4a' />
    +      </encryption>
    + + diff --git a/docs/schemas/Makefile.am b/docs/schemas/Makefile.am index a064518607..c217d69482 100644 --- a/docs/schemas/Makefile.am +++ b/docs/schemas/Makefile.am @@ -6,6 +6,7 @@ schema_DATA = \ interface.rng \ network.rng \ secret.rng \ + storageencryption.rng \ storagepool.rng \ storagevol.rng \ nodedev.rng \ diff --git a/docs/schemas/storageencryption.rng b/docs/schemas/storageencryption.rng new file mode 100644 index 0000000000..8f9cd6260b --- /dev/null +++ b/docs/schemas/storageencryption.rng @@ -0,0 +1,34 @@ + + + + + + + + default + qcow + + + + + + + + + + + + + passphrase + + + + + + + + + + + diff --git a/docs/sitemap.html b/docs/sitemap.html index 901633d502..24300d56db 100644 --- a/docs/sitemap.html +++ b/docs/sitemap.html @@ -135,6 +135,9 @@
  • Storage The storage pool and volume XML format +
  • + Storage Encryption + Storage volume encryption XML format
  • Capabilities The driver capabilities XML format diff --git a/docs/sitemap.html.in b/docs/sitemap.html.in index 2ed25c6cac..65de169f73 100644 --- a/docs/sitemap.html.in +++ b/docs/sitemap.html.in @@ -98,6 +98,10 @@ Storage The storage pool and volume XML format
  • +
  • + Storage Encryption + Storage volume encryption XML format +
  • Capabilities The driver capabilities XML format diff --git a/libvirt.spec.in b/libvirt.spec.in index 966cdf137a..1c04fae360 100644 --- a/libvirt.spec.in +++ b/libvirt.spec.in @@ -582,6 +582,7 @@ fi %{_datadir}/libvirt/schemas/capability.rng %{_datadir}/libvirt/schemas/interface.rng %{_datadir}/libvirt/schemas/secret.rng +%{_datadir}/libvirt/schemas/storageencryption.rng %if %{with_sasl} %config(noreplace) %{_sysconfdir}/sasl2/libvirt.conf diff --git a/mingw32-libvirt.spec.in b/mingw32-libvirt.spec.in index 093c45a08b..769c3ff120 100644 --- a/mingw32-libvirt.spec.in +++ b/mingw32-libvirt.spec.in @@ -95,6 +95,7 @@ rm -rf $RPM_BUILD_ROOT %{_mingw32_datadir}/libvirt/schemas/capability.rng %{_mingw32_datadir}/libvirt/schemas/interface.rng %{_mingw32_datadir}/libvirt/schemas/secret.rng +%{_mingw32_datadir}/libvirt/schemas/storageencryption.rng %{_mingw32_datadir}/locale/*/LC_MESSAGES/libvirt.mo diff --git a/po/POTFILES.in b/po/POTFILES.in index 66d3ebd7f7..0a53dab069 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -40,6 +40,7 @@ src/storage_backend_logical.c src/storage_backend_scsi.c src/storage_conf.c src/storage_driver.c +src/storage_encryption_conf.c src/test.c src/uml_conf.c src/uml_driver.c diff --git a/src/Makefile.am b/src/Makefile.am index 9567490770..bedeb840cc 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -52,6 +52,7 @@ UTIL_SOURCES = \ memory.c memory.h \ pci.c pci.h \ qparams.c qparams.h \ + storage_encryption_conf.h storage_encryption_conf.c \ threads.c threads.h \ threads-pthread.h \ threads-win32.h \ diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index f2c0736447..8db9fcd96d 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -344,6 +344,11 @@ virStoragePartedFsTypeTypeToString; virStoragePoolObjLock; virStoragePoolObjUnlock; +virStorageEncryptionFree; +virStorageEncryptionDropSecrets; +virStorageEncryptionParseNode; +virStorageEncryptionFormat; + # threads.h virMutexInit; diff --git a/src/storage_encryption_conf.c b/src/storage_encryption_conf.c new file mode 100644 index 0000000000..69cfaf110c --- /dev/null +++ b/src/storage_encryption_conf.c @@ -0,0 +1,241 @@ +/* + * storage_encryption_conf.h: volume encryption information + * + * Copyright (C) 2009 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Red Hat Author: Miloslav Trmač + */ + +#include + +#include "internal.h" + +#include "base64.h" +#include "buf.h" +#include "memory.h" +#include "storage_conf.h" +#include "storage_encryption_conf.h" +#include "util.h" +#include "xml.h" +#include "virterror_internal.h" + +#define VIR_FROM_THIS VIR_FROM_STORAGE + +VIR_ENUM_IMPL(virStorageEncryptionSecretType, + VIR_STORAGE_ENCRYPTION_SECRET_TYPE_LAST, "passphrase") + +VIR_ENUM_IMPL(virStorageEncryptionFormat, + VIR_STORAGE_ENCRYPTION_FORMAT_LAST, + "default", "qcow") + +static void +virStorageEncryptionSecretFree(virStorageEncryptionSecretPtr secret) +{ + if (!secret) + return; + VIR_FREE(secret->uuid); + VIR_FREE(secret); +} + +void +virStorageEncryptionFree(virStorageEncryptionPtr enc) +{ + size_t i; + + if (!enc) + return; + + for (i = 0; i < enc->nsecrets; i++) + virStorageEncryptionSecretFree(enc->secrets[i]); + VIR_FREE(enc->secrets); + VIR_FREE(enc); +} + +static virStorageEncryptionSecretPtr +virStorageEncryptionSecretParse(virConnectPtr conn, xmlXPathContextPtr ctxt, + xmlNodePtr node) +{ + xmlNodePtr old_node; + virStorageEncryptionSecretPtr ret; + char *type_str; + int type; + + if (VIR_ALLOC(ret) < 0) { + virReportOOMError(conn); + return NULL; + } + + old_node = ctxt->node; + ctxt->node = node; + + type_str = virXPathString(conn, "string(./@type)", ctxt); + if (type_str == NULL) { + virStorageReportError(conn, VIR_ERR_XML_ERROR, "%s", + _("unknown volume encryption secret type")); + goto cleanup; + } + type = virStorageEncryptionSecretTypeTypeFromString(type_str); + if (type < 0) { + virStorageReportError(conn, VIR_ERR_XML_ERROR, + _("unknown volume encryption secret type %s"), + type_str); + VIR_FREE(type_str); + goto cleanup; + } + VIR_FREE(type_str); + ret->type = type; + + ret->uuid = virXPathString(conn, "string(./@uuid)", ctxt); + ctxt->node = old_node; + return ret; + + cleanup: + virStorageEncryptionSecretFree(ret); + ctxt->node = old_node; + return NULL; +} + +static virStorageEncryptionPtr +virStorageEncryptionParseXML(virConnectPtr conn, xmlXPathContextPtr ctxt) +{ + xmlNodePtr *nodes = NULL; + virStorageEncryptionPtr ret; + char *format_str; + int format, i, n; + + if (VIR_ALLOC(ret) < 0) { + virReportOOMError(conn); + return NULL; + } + + format_str = virXPathString(conn, "string(./@format)", ctxt); + if (format_str == NULL) { + virStorageReportError(conn, VIR_ERR_XML_ERROR, "%s", + _("unknown volume encryption format")); + goto cleanup; + } + format = virStorageEncryptionFormatTypeFromString(format_str); + if (format < 0) { + virStorageReportError(conn, VIR_ERR_XML_ERROR, + _("unknown volume encryption format type %s"), + format_str); + VIR_FREE(format_str); + goto cleanup; + } + VIR_FREE(format_str); + ret->format = format; + + n = virXPathNodeSet(conn, "./secret", ctxt, &nodes); + if (n < 0){ + virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s", + _("cannot extract volume encryption secrets")); + goto cleanup; + } + if (n != 0 && VIR_ALLOC_N(ret->secrets, n) < 0) { + virReportOOMError(conn); + goto cleanup; + } + ret->nsecrets = n; + for (i = 0; i < n; i++) { + ret->secrets[i] = virStorageEncryptionSecretParse(conn, ctxt, nodes[i]); + if (ret->secrets[i] == NULL) + goto cleanup; + } + VIR_FREE(nodes); + + return ret; + + cleanup: + VIR_FREE(nodes); + virStorageEncryptionFree(ret); + return NULL; +} + +virStorageEncryptionPtr +virStorageEncryptionParseNode(virConnectPtr conn, + xmlDocPtr xml, xmlNodePtr root) +{ + xmlXPathContextPtr ctxt = NULL; + virStorageEncryptionPtr enc = NULL; + + if (STRNEQ((const char *) root->name, "encryption")) { + virStorageReportError(conn, VIR_ERR_XML_ERROR, + "%s", _("unknown root element for volume " + "encryption information")); + goto cleanup; + } + + ctxt = xmlXPathNewContext(xml); + if (ctxt == NULL) { + virReportOOMError(conn); + goto cleanup; + } + + ctxt->node = root; + enc = virStorageEncryptionParseXML(conn, ctxt); + + cleanup: + xmlXPathFreeContext(ctxt); + return enc; +} + +static int +virStorageEncryptionSecretFormat(virConnectPtr conn, + virBufferPtr buf, + virStorageEncryptionSecretPtr secret) +{ + const char *type; + + type = virStorageEncryptionSecretTypeTypeToString(secret->type); + if (!type) { + virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s", + _("unexpected volume encryption secret type")); + return -1; + } + + virBufferVSprintf(buf, " uuid != NULL) + virBufferEscapeString(buf, " uuid='%s'", secret->uuid); + virBufferAddLit(buf, "/>\n"); + return 0; +} + +int +virStorageEncryptionFormat(virConnectPtr conn, + virBufferPtr buf, + virStorageEncryptionPtr enc) +{ + const char *format; + size_t i; + + format = virStorageEncryptionFormatTypeToString(enc->format); + if (!format) { + virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("unexpected encryption format")); + return -1; + } + virBufferVSprintf(buf, " \n", format); + + for (i = 0; i < enc->nsecrets; i++) { + if (virStorageEncryptionSecretFormat(conn, buf, enc->secrets[i]) < 0) + return -1; + } + + virBufferAddLit(buf, " \n"); + + return 0; +} diff --git a/src/storage_encryption_conf.h b/src/storage_encryption_conf.h new file mode 100644 index 0000000000..3e653b5ab8 --- /dev/null +++ b/src/storage_encryption_conf.h @@ -0,0 +1,72 @@ +/* + * storage_encryption_conf.h: volume encryption information + * + * Copyright (C) 2009 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Red Hat Author: Miloslav Trmač + */ + +#ifndef __VIR_STORAGE_ENCRYPTION_H__ +#define __VIR_STORAGE_ENCRYPTION_H__ + +#include "internal.h" +#include "buf.h" +#include "util.h" + +#include +#include + +enum virStorageEncryptionSecretType { + VIR_STORAGE_ENCRYPTION_SECRET_TYPE_PASSPHRASE = 0, + + VIR_STORAGE_ENCRYPTION_SECRET_TYPE_LAST +}; +VIR_ENUM_DECL(virStorageEncryptionSecretType) + +typedef struct _virStorageEncryptionSecret virStorageEncryptionSecret; +typedef virStorageEncryptionSecret *virStorageEncryptionSecretPtr; +struct _virStorageEncryptionSecret { + int type; /* enum virStorageEncryptionSecretType */ + char *uuid; +}; + +enum virStorageEncryptionFormat { + /* "default" is only valid for volume creation */ + VIR_STORAGE_ENCRYPTION_FORMAT_DEFAULT = 0, + VIR_STORAGE_ENCRYPTION_FORMAT_QCOW, /* Both qcow and qcow2 */ + + VIR_STORAGE_ENCRYPTION_FORMAT_LAST, +}; +VIR_ENUM_DECL(virStorageEncryptionFormat) + +typedef struct _virStorageEncryption virStorageEncryption; +typedef virStorageEncryption *virStorageEncryptionPtr; +struct _virStorageEncryption { + int format; /* enum virStorageEncryptionFormat */ + + size_t nsecrets; + virStorageEncryptionSecretPtr *secrets; +}; + +void virStorageEncryptionFree(virStorageEncryptionPtr enc); +virStorageEncryptionPtr virStorageEncryptionParseNode(virConnectPtr conn, + xmlDocPtr xml, + xmlNodePtr root); +int virStorageEncryptionFormat(virConnectPtr conn, virBufferPtr buf, + virStorageEncryptionPtr enc); + +#endif /* __VIR_STORAGE_ENCRYPTION_H__ */