From: Jonathon Jongsma Date: Thu, 22 Dec 2022 22:56:47 +0000 (-0600) Subject: qemu: implement keyfile auth for ssh disks with nbdkit X-Git-Tag: v9.8.0-rc1~21 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=68599168ea8185689bd227e6d142e3d933558f84;p=thirdparty%2Flibvirt.git qemu: implement keyfile auth for ssh disks with nbdkit For ssh disks that are served by nbdkit, we can support logging in with an ssh key file. Pass the path to the configured key file and the username to the nbdkit process. Signed-off-by: Jonathon Jongsma Reviewed-by: Peter Krempa --- diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 2eec9177da..c23dda673e 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -7219,10 +7219,18 @@ virDomainDiskSourceNetworkParse(xmlNodePtr node, return -1; } } - if (src->protocol == VIR_STORAGE_NET_PROTOCOL_SSH && - (tmpnode = virXPathNode("./knownHosts", ctxt))) { - if (!(src->ssh_known_hosts_file = virXMLPropStringRequired(tmpnode, "path"))) - return -1; + if (src->protocol == VIR_STORAGE_NET_PROTOCOL_SSH) { + if ((tmpnode = virXPathNode("./knownHosts", ctxt))) { + if (!(src->ssh_known_hosts_file = virXMLPropStringRequired(tmpnode, "path"))) + return -1; + } + if ((tmpnode = virXPathNode("./identity", ctxt))) { + if (!(src->ssh_user = virXMLPropStringRequired(tmpnode, "username"))) + return -1; + + if (!(src->ssh_keyfile = virXMLPropStringRequired(tmpnode, "keyfile"))) + return -1; + } } return 0; @@ -22211,8 +22219,18 @@ virDomainDiskSourceFormatNetwork(virBuffer *attrBuf, if (src->timeout) virBufferAsprintf(childBuf, "\n", src->timeout); - if (src->protocol == VIR_STORAGE_NET_PROTOCOL_SSH && src->ssh_known_hosts_file) - virBufferEscapeString(childBuf, "\n", src->ssh_known_hosts_file); + if (src->protocol == VIR_STORAGE_NET_PROTOCOL_SSH) { + if (src->ssh_known_hosts_file) + virBufferEscapeString(childBuf, "\n", src->ssh_known_hosts_file); + if (src->ssh_keyfile) { + virBufferAddLit(childBuf, "ssh_user); + virBufferEscapeString(childBuf, " keyfile='%s'", src->ssh_keyfile); + + virBufferAddLit(childBuf, "/>\n"); + } + } } diff --git a/src/conf/storage_source_conf.c b/src/conf/storage_source_conf.c index 0a39779d52..67d50af074 100644 --- a/src/conf/storage_source_conf.c +++ b/src/conf/storage_source_conf.c @@ -898,6 +898,7 @@ virStorageSourceCopy(const virStorageSource *src, def->ssh_host_key_check_disabled = src->ssh_host_key_check_disabled; def->ssh_user = g_strdup(src->ssh_user); def->ssh_known_hosts_file = g_strdup(src->ssh_known_hosts_file); + def->ssh_keyfile = g_strdup(src->ssh_keyfile); def->nfs_user = g_strdup(src->nfs_user); def->nfs_group = g_strdup(src->nfs_group); @@ -1177,6 +1178,7 @@ virStorageSourceClear(virStorageSource *def) VIR_FREE(def->ssh_user); VIR_FREE(def->ssh_known_hosts_file); + VIR_FREE(def->ssh_keyfile); VIR_FREE(def->nfs_user); VIR_FREE(def->nfs_group); diff --git a/src/conf/storage_source_conf.h b/src/conf/storage_source_conf.h index a2b2244844..3b6e628e21 100644 --- a/src/conf/storage_source_conf.h +++ b/src/conf/storage_source_conf.h @@ -408,12 +408,11 @@ struct _virStorageSource { bool hostcdrom; /* backing device is a cdrom */ - /* passthrough variables for the ssh driver which we don't handle properly */ - /* these must not be used apart from formatting the output JSON in the qemu driver */ + /* ssh variables */ char *ssh_user; bool ssh_host_key_check_disabled; - /* additional ssh variables */ char *ssh_known_hosts_file; + char *ssh_keyfile; /* nfs_user and nfs_group store the strings passed in by the user for NFS params. * nfs_uid and nfs_gid represent the converted/looked up ID numbers which are used diff --git a/src/qemu/qemu_nbdkit.c b/src/qemu/qemu_nbdkit.c index afac71e21a..0a6c7962b0 100644 --- a/src/qemu/qemu_nbdkit.c +++ b/src/qemu/qemu_nbdkit.c @@ -1049,8 +1049,12 @@ qemuNbdkitProcessBuildCommandSSH(qemuNbdkitProcess *proc, if (proc->source->auth) { if (qemuNbdkitProcessBuildCommandAuth(proc->source->auth, cmd) < 0) return -1; - } else if (proc->source->ssh_user) { - virCommandAddArgPair(cmd, "user", proc->source->ssh_user); + } else { + if (proc->source->ssh_keyfile) + virCommandAddArgPair(cmd, "identity", proc->source->ssh_keyfile); + + if (proc->source->ssh_user) + virCommandAddArgPair(cmd, "user", proc->source->ssh_user); } if (proc->source->ssh_host_key_check_disabled) @@ -1171,6 +1175,10 @@ qemuNbdkitProcessStart(qemuNbdkitProcess *proc, if (qemuExtDeviceLogCommand(driver, vm, cmd, "nbdkit") < 0) goto error; + if (proc->source->ssh_keyfile && + qemuSecurityDomainSetPathLabel(driver, vm, proc->source->ssh_keyfile, false) < 0) + goto error; + if (proc->source->ssh_known_hosts_file && qemuSecurityDomainSetPathLabel(driver, vm, proc->source->ssh_known_hosts_file, false) < 0) goto error; @@ -1256,6 +1264,9 @@ qemuNbdkitProcessStop(qemuNbdkitProcess *proc, if (proc->source->ssh_known_hosts_file) qemuSecurityDomainRestorePathLabel(driver, vm, proc->source->ssh_known_hosts_file); + if (proc->source->ssh_keyfile) + qemuSecurityDomainRestorePathLabel(driver, vm, proc->source->ssh_keyfile); + if (proc->pid < 0) return 0; diff --git a/tests/qemunbdkitdata/disk-network-ssh-key.args.disk0 b/tests/qemunbdkitdata/disk-network-ssh-key.args.disk0 new file mode 100644 index 0000000000..0b52bfe0fb --- /dev/null +++ b/tests/qemunbdkitdata/disk-network-ssh-key.args.disk0 @@ -0,0 +1,9 @@ +nbdkit \ +--unix /tmp/statedir-0/nbdkit-test-disk-0.socket \ +--foreground ssh \ +host=example.org \ +port=2222 \ +path=test.img \ +identity=/path/to/id_rsa \ +user=myuser \ +known-hosts=/path/to/ssh_known_hosts diff --git a/tests/qemunbdkitdata/disk-network-ssh.args.disk2 b/tests/qemunbdkitdata/disk-network-ssh.args.disk2 new file mode 100644 index 0000000000..e269a34351 --- /dev/null +++ b/tests/qemunbdkitdata/disk-network-ssh.args.disk2 @@ -0,0 +1,9 @@ +nbdkit \ +--unix /tmp/statedir-2/nbdkit-test-disk-2.socket \ +--foreground ssh \ +host=example.org \ +port=2222 \ +path=test2.img \ +identity=/path/to/id_rsa \ +user=myuser \ +known-hosts=/path/to/ssh_known_hosts diff --git a/tests/qemunbdkittest.c b/tests/qemunbdkittest.c index a51b287f34..559196a1cd 100644 --- a/tests/qemunbdkittest.c +++ b/tests/qemunbdkittest.c @@ -299,6 +299,7 @@ mymain(void) DO_TEST("disk-network-source-curl", QEMU_NBDKIT_CAPS_PLUGIN_CURL); DO_TEST("disk-network-ssh", QEMU_NBDKIT_CAPS_PLUGIN_SSH); DO_TEST("disk-network-ssh-password", QEMU_NBDKIT_CAPS_PLUGIN_SSH); + DO_TEST("disk-network-ssh-key", QEMU_NBDKIT_CAPS_PLUGIN_SSH); cleanup: qemuTestDriverFree(&driver); diff --git a/tests/qemuxml2argvdata/disk-network-ssh-key.xml b/tests/qemuxml2argvdata/disk-network-ssh-key.xml new file mode 100644 index 0000000000..81b92231fa --- /dev/null +++ b/tests/qemuxml2argvdata/disk-network-ssh-key.xml @@ -0,0 +1,33 @@ + + QEMUGuest1 + c7a5fdbd-edaf-9455-926a-d65c16db1809 + 219136 + 219136 + 1 + + hvm + + + + destroy + restart + destroy + + + + + + + + + + + + + + + + + + +