[libvirt] [PATCH 3/3] qemu: Introduce qemuBuildMasterKeyCommandLine

John Ferlan jferlan at redhat.com
Thu Mar 24 17:53:21 UTC 2016


If the -object secret capability exists, then get the path to the
base64 encoded masterKey file and provide that to qemu. Checking
for the existence of the file before passing to qemu could be done,
but causes issues in mock test environment.

Since the qemuDomainObjPrivate is not available when building the
command line, the qemuBuildHasMasterKey API will have to suffice
as the primary arbiter for whether the capability exists in order
to find/return the path to the master key for usage.

Created the qemuDomainGetMasterKeyAlias API which will be used by
later patches to define the 'keyid' (eg, masterKey) to be used by
other secrets to provide the id to qemu for the master key.

Signed-off-by: John Ferlan <jferlan at redhat.com>
---
 src/qemu/qemu_alias.c                              | 17 ++++++
 src/qemu/qemu_alias.h                              |  3 +
 src/qemu/qemu_command.c                            | 68 ++++++++++++++++++++++
 .../qemuxml2argvdata/qemuxml2argv-master-key.args  | 23 ++++++++
 tests/qemuxml2argvdata/qemuxml2argv-master-key.xml | 30 ++++++++++
 tests/qemuxml2argvtest.c                           |  2 +
 6 files changed, 143 insertions(+)
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-master-key.args
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-master-key.xml

diff --git a/src/qemu/qemu_alias.c b/src/qemu/qemu_alias.c
index efd9222..b57b967 100644
--- a/src/qemu/qemu_alias.c
+++ b/src/qemu/qemu_alias.c
@@ -484,3 +484,20 @@ qemuAssignDeviceAliases(virDomainDefPtr def, virQEMUCapsPtr qemuCaps)
 
     return 0;
 }
+
+
+/* qemuDomainGetMasterKeyAlias:
+ *
+ * Generate and return the masterKey alias
+ *
+ * Returns NULL or a string containing the master key alias
+ */
+char *
+qemuDomainGetMasterKeyAlias(void)
+{
+    char *alias;
+
+    ignore_value(VIR_STRDUP(alias, "masterKey0"));
+
+    return alias;
+}
diff --git a/src/qemu/qemu_alias.h b/src/qemu/qemu_alias.h
index a2eaa27..299a6d4 100644
--- a/src/qemu/qemu_alias.h
+++ b/src/qemu/qemu_alias.h
@@ -61,4 +61,7 @@ int qemuAssignDeviceAliases(virDomainDefPtr def, virQEMUCapsPtr qemuCaps);
 
 int qemuDomainDeviceAliasIndex(const virDomainDeviceInfo *info,
                                const char *prefix);
+
+char *qemuDomainGetMasterKeyAlias(void);
+
 #endif /* __QEMU_ALIAS_H__*/
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 0331789..2b1dc93 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -151,6 +151,71 @@ VIR_ENUM_IMPL(qemuNumaPolicy, VIR_DOMAIN_NUMATUNE_MEM_LAST,
               "interleave");
 
 /**
+ * qemuBuildHasMasterKey:
+ * @qemuCaps: QEMU binary capabilities
+ *
+ * Return true if this binary supports the secret -object, false otherwise.
+ */
+static bool
+qemuBuildHasMasterKey(virQEMUCapsPtr qemuCaps)
+{
+    return virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_SECRET);
+}
+
+
+/**
+ * qemuBuildMasterKeyCommandLine:
+ * @cmd: the command to modify
+ * @qemuCaps qemu capabilities object
+ * @domainLibDir: location to find the master key
+
+ * Formats the command line for a master key if available
+ *
+ * Returns 0 on success, -1 w/ error message on failure
+ */
+static int
+qemuBuildMasterKeyCommandLine(virCommandPtr cmd,
+                              virQEMUCapsPtr qemuCaps,
+                              const char *domainLibDir)
+{
+    int ret = -1;
+    char *alias = NULL;
+    char *path = NULL;
+
+    /* If the -object secret does not exist, then just return. This just
+     * means the domain won't be able to use a secret master key and is
+     * not a failure.
+     */
+    if (!qemuBuildHasMasterKey(qemuCaps)) {
+        VIR_INFO("secret object is not supported by this QEMU binary");
+        return 0;
+    }
+
+    if (!(alias = qemuDomainGetMasterKeyAlias()))
+        return -1;
+
+    /* Get the path. NB, the mocked test will not have the created
+     * file so we cannot check for existence, which is no different
+     * than other command line options which do not check for the
+     * existence of socket files before using.
+     */
+    if (!(path = qemuDomainGetMasterKeyFilePath(domainLibDir)))
+        goto cleanup;
+
+    virCommandAddArg(cmd, "-object");
+    virCommandAddArgFormat(cmd, "secret,id=%s,format=base64,file=%s",
+                           alias, path);
+
+    ret = 0;
+
+ cleanup:
+    VIR_FREE(alias);
+    VIR_FREE(path);
+    return ret;
+}
+
+
+/**
  * qemuVirCommandGetFDSet:
  * @cmd: the command to modify
  * @fd: fd to reassign to the child
@@ -9224,6 +9289,9 @@ qemuBuildCommandLine(virConnectPtr conn,
     if (!standalone)
         virCommandAddArg(cmd, "-S"); /* freeze CPU */
 
+    if (qemuBuildMasterKeyCommandLine(cmd, qemuCaps, domainLibDir) < 0)
+        goto error;
+
     if (enableFips)
         virCommandAddArg(cmd, "-enable-fips");
 
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-master-key.args b/tests/qemuxml2argvdata/qemuxml2argv-master-key.args
new file mode 100644
index 0000000..14a3597
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-master-key.args
@@ -0,0 +1,23 @@
+LC_ALL=C \
+PATH=/bin \
+HOME=/home/test \
+USER=test \
+LOGNAME=test \
+QEMU_AUDIO_DRV=none \
+/usr/bin/qemu \
+-name QEMUGuest1 \
+-S \
+-object secret,id=masterKey0,format=base64,\
+file=/tmp/lib/domain--1-QEMUGuest1/master.key \
+-M pc \
+-m 214 \
+-smp 2 \
+-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \
+-nographic \
+-nodefaults \
+-monitor unix:/tmp/lib/domain--1-QEMUGuest1/monitor.sock,server,nowait \
+-no-acpi \
+-boot c \
+-usb \
+-drive file=/dev/HostVG/QEMUGuest1,format=raw,if=none,id=drive-ide0-0-0 \
+-device ide-drive,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-master-key.xml b/tests/qemuxml2argvdata/qemuxml2argv-master-key.xml
new file mode 100644
index 0000000..f2adb84
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-master-key.xml
@@ -0,0 +1,30 @@
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory unit='KiB'>219136</memory>
+  <currentMemory unit='KiB'>219136</currentMemory>
+  <vcpu placement='static'>2</vcpu>
+  <os>
+    <type arch='i686' machine='pc'>hvm</type>
+    <boot dev='hd'/>
+  </os>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu</emulator>
+    <disk type='block' device='disk'>
+      <driver name='qemu' type='raw'/>
+      <source dev='/dev/HostVG/QEMUGuest1'/>
+      <target dev='hda' bus='ide'/>
+      <address type='drive' controller='0' bus='0' target='0' unit='0'/>
+    </disk>
+    <controller type='usb' index='0'/>
+    <controller type='ide' index='0'/>
+    <controller type='pci' index='0' model='pci-root'/>
+    <input type='mouse' bus='ps2'/>
+    <input type='keyboard' bus='ps2'/>
+    <memballoon model='none'/>
+  </devices>
+</domain>
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index e9b8d64..5f492cb 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -1864,6 +1864,8 @@ mymain(void)
 
     DO_TEST("debug-threads", QEMU_CAPS_NAME_DEBUG_THREADS);
 
+    DO_TEST("master-key", QEMU_CAPS_OBJECT_SECRET);
+
     qemuTestDriverFree(&driver);
 
     return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
-- 
2.5.0




More information about the libvir-list mailing list