The following describes the behavior of TLS for VxHS block device:
(1) Two new options have been added in /etc/libvirt/qemu.conf
to control TLS behavior with VxHS block devices
"vxhs_tls" and "vxhs_tls_x509_cert_dir".
(2) Setting "vxhs_tls=1" in /etc/libvirt/qemu.conf will enable
TLS for VxHS block devices.
(3) "vxhs_tls_x509_cert_dir" can be set to the full path where the
TLS certificates and keys are saved. If this value is missing,
the "default_tls_x509_cert_dir" will be used instead.
(4) If the value of "vxhs_tls" is set to 1, TLS creds will be added
automatically on the qemu command line for every VxHS
block device.
(5) With "vxhs_tls=1", TLS may selectively be disabled on individual
VxHS disks by specifying tls='no' in the device domain
specification.
(6) Valid values for domain TLS setting are tls='yes|no'.
(7) tls='yes' can only be specified if "vxhs_tls" is enabled.
Specifying tls='yes' when "vxhs_tls=0" results in an error.
QEMU changes for VxHS (including TLS support) are already upstream.
Sample TLS args generated by libvirt -
-object tls-creds-x509,id=objvxhs_tls0,dir=/usr/local/etc/pki/qemu,\
endpoint=client,verify-peer=yes \
-drive file.driver=vxhs,file.tls-creds=objvxhs_tls0,\
file.vdisk-id=eb90327c-8302-4725-9e1b-4e85ed4dc251,\
file.server.host=192.168.0.1,file.server.port=9999,format=raw,if=none,\
id=drive-virtio-disk0,cache=none \
-device virtio-blk-pci,bus=pci.0,addr=0x4,drive=drive-virtio-disk0,\
id=virtio-disk0
Signed-off-by: Ashish Mittal <Ashish.Mittal(a)veritas.com>
---
v5 changelog:
(1) The v4 3/3 patch has been split into smaller chunks.
(2) Functionally there are no changes in TLS code yet.
TODO: Changes to TLS functionality are pending.
docs/schemas/domaincommon.rng | 5 ++++
src/conf/domain_conf.c | 19 ++++++++++++
src/qemu/qemu_block.c | 42 +++++++++++++++++++--------
src/qemu/qemu_command.c | 67 +++++++++++++++++++++++++++++++++++++++++++
src/util/virstoragefile.c | 13 +++++++++
src/util/virstoragefile.h | 9 ++++++
6 files changed, 143 insertions(+), 12 deletions(-)
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 458b8d8..af38c9a 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -1651,6 +1651,11 @@
</attribute>
<attribute name="name"/>
<ref name="diskSourceNetworkHost"/>
+ <optional>
+ <attribute name="tls">
+ <ref name="virYesNo"/>
+ </attribute>
+ </optional>
</element>
</define>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 5bad397..f3fb3d0 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -8017,6 +8017,7 @@ virDomainDiskSourceParse(xmlNodePtr node,
int ret = -1;
char *protocol = NULL;
xmlNodePtr saveNode = ctxt->node;
+ char *haveTLS = NULL;
ctxt->node = node;
@@ -8050,6 +8051,19 @@ virDomainDiskSourceParse(xmlNodePtr node,
goto cleanup;
}
+ /* Check tls=yes|no domain setting for the block device */
+ /* At present only VxHS. Other block devices may be added later */
+ if ((haveTLS = virXMLPropString(node, "tls")) &&
+ src->protocol == VIR_STORAGE_NET_PROTOCOL_VXHS) {
+ if ((src->haveTLS =
+ virTristateBoolTypeFromString(haveTLS)) <= 0) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("unknown VxHS 'tls' setting
'%s'"),
+ haveTLS);
+ goto cleanup;
+ }
+ }
+
/* for historical reasons the volume name for gluster volume is stored
* as a part of the path. This is hard to work with when dealing with
* relative names. Split out the volume into a separate variable */
@@ -8105,6 +8119,7 @@ virDomainDiskSourceParse(xmlNodePtr node,
cleanup:
VIR_FREE(protocol);
+ VIR_FREE(haveTLS);
ctxt->node = saveNode;
return ret;
}
@@ -21534,6 +21549,10 @@ virDomainDiskSourceFormatNetwork(virBufferPtr buf,
VIR_FREE(path);
+ if (src->haveTLS != VIR_TRISTATE_BOOL_ABSENT)
+ virBufferAsprintf(buf, " tls='%s'",
+ virTristateBoolTypeToString(src->haveTLS));
+
if (src->nhosts == 0 && !src->snapshot && !src->configFile)
{
virBufferAddLit(buf, "/>\n");
} else {
diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c
index a4d0160..766d07f 100644
--- a/src/qemu/qemu_block.c
+++ b/src/qemu/qemu_block.c
@@ -519,20 +519,38 @@ qemuBlockStorageSourceGetVxHSProps(virStorageSourcePtr src)
if (!(server = qemuBuildVxHSDriveJSONHost(src)))
return NULL;
- /* VxHS disk specification example:
- * { driver:"vxhs",
- * vdisk-id:"eb90327c-8302-4725-4e85ed4dc251",
- * server.host:"1.2.3.4",
- * server.port:1234}
- */
- if (virJSONValueObjectCreate(&ret,
- "s:driver", protocol,
- "s:vdisk-id", src->path,
- "a:server", server, NULL) < 0) {
- virJSONValueFree(server);
- ret = NULL;
+ if (src->addTLS == true) {
+ char *objalias = NULL;
+
+ if (!(objalias = qemuAliasTLSObjFromSrcAlias("vxhs")))
+ goto cleanup;
+
+ if (virJSONValueObjectCreate(&ret,
+ "s:driver", protocol,
+ "s:tls-creds", objalias,
+ "s:vdisk-id", src->path,
+ "a:server", server, NULL) < 0) {
+ virJSONValueFree(server);
+ ret = NULL;
+ }
+ VIR_FREE(objalias);
+ } else {
+ /* VxHS disk specification example:
+ * { driver:"vxhs",
+ * vdisk-id:"eb90327c-8302-4725-4e85ed4dc251",
+ * server.host:"1.2.3.4",
+ * server.port:1234}
+ */
+ if (virJSONValueObjectCreate(&ret,
+ "s:driver", protocol,
+ "s:vdisk-id", src->path,
+ "a:server", server, NULL) < 0) {
+ virJSONValueFree(server);
+ ret = NULL;
+ }
}
+ cleanup:
return ret;
}
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 0fd2674..384a489 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -791,6 +791,70 @@ qemuBuildTLSx509CommandLine(virCommandPtr cmd,
}
+
+/* qemuBuildDiskVxHSTLSinfoCommandLine:
+ * @cmd: Pointer to the command string
+ * @cfg: Pointer to the qemu driver config
+ * @disk: The disk we are processing
+ * @qemuCaps: qemu capabilities object
+ *
+ * Check if the VxHS disk meets all the criteria to enable TLS.
+ * If yes, add a new TLS object and mention it's ID on the disk
+ * command line.
+ *
+ * Returns 0 on success, -1 w/ error on some sort of failure.
+ */
+static int
+qemuBuildDiskVxHSTLSinfoCommandLine(virCommandPtr cmd,
+ virQEMUDriverConfigPtr cfg,
+ virDomainDiskDefPtr disk,
+ virQEMUCapsPtr qemuCaps)
+{
+ int ret = 0;
+
+ if (cfg->vxhsTLS == true && disk->src->haveTLS !=
VIR_TRISTATE_BOOL_NO) {
+ disk->src->addTLS = true;
+ ret = qemuBuildTLSx509CommandLine(cmd, cfg->vxhsTLSx509certdir,
+ false,
+ true,
+ false,
+ "vxhs",
+ qemuCaps);
+ } else if (cfg->vxhsTLS == false &&
+ disk->src->haveTLS == VIR_TRISTATE_BOOL_YES) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Please enable VxHS specific TLS options in the qemu
"
+ "conf file before using TLS in VxHS device domain "
+ "specification"));
+ ret = -1;
+ }
+
+ return ret;
+}
+
+
+/* qemuBuildDiskTLSinfoCommandLine:
+ *
+ * Add TLS object if the disk uses a secure communication channel
+ *
+ * Returns 0 on success, -1 w/ error on some sort of failure.
+ */
+static int
+qemuBuildDiskTLSinfoCommandLine(virCommandPtr cmd,
+ virQEMUDriverConfigPtr cfg,
+ virDomainDiskDefPtr disk,
+ virQEMUCapsPtr qemuCaps)
+{
+ virStorageSourcePtr src = disk->src;
+
+ /* other protocols may be added later */
+ if (src->protocol == VIR_STORAGE_NET_PROTOCOL_VXHS)
+ return qemuBuildDiskVxHSTLSinfoCommandLine(cmd, cfg, disk, qemuCaps);
+
+ return 0;
+}
+
+
static char *
qemuBuildNetworkDriveURI(virStorageSourcePtr src,
qemuDomainSecretInfoPtr secinfo)
@@ -2218,6 +2282,9 @@ qemuBuildDiskDriveCommandLine(virCommandPtr cmd,
if (qemuBuildDiskSecinfoCommandLine(cmd, encinfo) < 0)
return -1;
+ if (qemuBuildDiskTLSinfoCommandLine(cmd, cfg, disk, qemuCaps) < 0)
+ return -1;
+
virCommandAddArg(cmd, "-drive");
if (!(optstr = qemuBuildDriveStr(disk, cfg, driveBoot, qemuCaps)))
diff --git a/src/util/virstoragefile.c b/src/util/virstoragefile.c
index e9a59e0..d4f0fdb 100644
--- a/src/util/virstoragefile.c
+++ b/src/util/virstoragefile.c
@@ -2039,6 +2039,8 @@ virStorageSourceCopy(const virStorageSource *src,
ret->physical = src->physical;
ret->readonly = src->readonly;
ret->shared = src->shared;
+ ret->haveTLS = src->haveTLS;
+ ret->addTLS = src->addTLS;
/* storage driver metadata are not copied */
ret->drv = NULL;
@@ -3219,6 +3221,7 @@ virStorageSourceParseBackingJSONVxHS(virStorageSourcePtr src,
{
const char *vdisk_id = virJSONValueObjectGetString(json, "vdisk-id");
virJSONValuePtr server = virJSONValueObjectGetObject(json, "server");
+ const char *haveTLS = virJSONValueObjectGetString(json, "tls");
if (!vdisk_id || !server) {
virReportError(VIR_ERR_INVALID_ARG, "%s",
@@ -3227,6 +3230,16 @@ virStorageSourceParseBackingJSONVxHS(virStorageSourcePtr src,
return -1;
}
+ if (haveTLS) {
+ if ((src->haveTLS =
+ virTristateBoolTypeFromString(haveTLS)) <= 0) {
+ virReportError(VIR_ERR_INVALID_ARG,
+ _("unknown VxHS 'tls' setting
'%s'"),
+ haveTLS);
+ return -1;
+ }
+ }
+
src->type = VIR_STORAGE_TYPE_NETWORK;
src->protocol = VIR_STORAGE_NET_PROTOCOL_VXHS;
diff --git a/src/util/virstoragefile.h b/src/util/virstoragefile.h
index f7e897f..0f363a7 100644
--- a/src/util/virstoragefile.h
+++ b/src/util/virstoragefile.h
@@ -281,6 +281,15 @@ struct _virStorageSource {
/* metadata that allows identifying given storage source */
char *nodeformat; /* name of the format handler object */
char *nodestorage; /* name of the storage object */
+
+ /* This is the domain specific setting.
+ * It may be absent */
+ int haveTLS; /* enum virTristateBool */
+
+ /* This should be set to "true" only when TLS creds are to be added for
+ * the device. For e.g. this could be based on a combination of
+ * global conf setting + domain specific setting */
+ bool addTLS;
};
--
2.5.5