Using the masterKey and if the capability exists build an -object secret
command line to pass a masterKey file to qemu. The qemuBuildHasMasterKey
is expected to be reused by other objects which would need to know not
only if the masterKey has been provided, but if the secret object can be
used for their own purposes.
Additionally, generate qemuDomainGetMasterKeyAlias 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.
Although the path to the domain libDir and the masterKey file are created
after qemuBuildCommandLine completes successfully, it's still possible to
generate the path and use it. No different than code paths that use the
domain libDir to create socket files (e.g. monitor.sock).
Signed-off-by: John Ferlan <jferlan(a)redhat.com>
---
src/qemu/qemu_command.c | 67 ++++++++++++++++++++++
src/qemu/qemu_domain.c | 17 ++++++
src/qemu/qemu_domain.h | 2 +
.../qemuxml2argvdata/qemuxml2argv-master-key.args | 23 ++++++++
tests/qemuxml2argvdata/qemuxml2argv-master-key.xml | 30 ++++++++++
tests/qemuxml2argvtest.c | 2 +
6 files changed, 141 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_command.c b/src/qemu/qemu_command.c
index eb02553..04e75fd 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -151,6 +151,70 @@ 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 path will not exist yet as domainLibDir
+ * and the master secret file gets created after we've successfully
+ * built the command line
+ */
+ 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
@@ -9220,6 +9284,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/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 507ae9e..53d6705 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -468,6 +468,23 @@ qemuDomainJobInfoToParams(qemuDomainJobInfoPtr jobInfo,
}
+/* 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;
+}
+
+
/* qemuDomainGetMasterKeyFilePath:
* @libDir: Directory path to domain lib files
*
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index b24acdf..60dbe82 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -550,6 +550,8 @@ int qemuDomainSetPrivatePaths(char **domainLibDir,
const char *domainName,
int domainId);
+char *qemuDomainGetMasterKeyAlias(void);
+
char *qemuDomainGetMasterKeyFilePath(const char *libDir);
int qemuDomainWriteMasterKeyFile(const char *libDir, const char *masterKey)
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 4fac77d..a9d5975 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -1897,6 +1897,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