From nobody Wed Feb 11 06:14:10 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of redhat.com designates 170.10.133.124 as permitted sender) client-ip=170.10.133.124; envelope-from=libvir-list-bounces@redhat.com; helo=us-smtp-delivery-124.mimecast.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1676394664; cv=none; d=zohomail.com; s=zohoarc; b=B0DzU8E0C9YzPv33J03VhxTCKP7mfo7iQji5mHXbaO2qp3ld1Nyyf2gyen9TzsCh5DBhHbRReH1z5CkWmTgDTWLuNoAQ8WhJ9T0nKEGcfUcm49F8GvOjgSm2xIxvMNCX5S4QzQcvnbaeUOEPbp8ddzYtE5H4uPK0TvsIjiVAnQI= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1676394664; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=aDvQGGOF/Xaz6UxKmcDFjT4RhYF53TOUTFZvTSzg/us=; b=nttMsizRbUGlzQ0JJTyjiB4TKAolAmn5FGYa1sw0pWm+dQVxkkPkd15Dcm94B/fYF/qTHxvcz4/9rlezf6ilm2Xwn85mPVB7zYog0gmWCLQv5Hbp0aRfaeAQuhsW4p3fwXy7qFvEvqqk6sLA/8KcaIzzYoDPNWD8eadY/3l4Cmk= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by mx.zohomail.com with SMTPS id 1676394664263567.4311846275705; Tue, 14 Feb 2023 09:11:04 -0800 (PST) Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-149-GOI5bsNUPyKw0R1w6cfcbw-1; Tue, 14 Feb 2023 12:10:14 -0500 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.rdu2.redhat.com [10.11.54.8]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 3C1BF800DAA; Tue, 14 Feb 2023 17:10:05 +0000 (UTC) Received: from mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (unknown [10.30.29.100]) by smtp.corp.redhat.com (Postfix) with ESMTP id 1D4EEC15BAE; Tue, 14 Feb 2023 17:10:05 +0000 (UTC) Received: from mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (localhost [IPv6:::1]) by mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (Postfix) with ESMTP id 966C31940376; Tue, 14 Feb 2023 17:09:22 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) by mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (Postfix) with ESMTP id 463C81946A42 for ; Tue, 14 Feb 2023 17:08:28 +0000 (UTC) Received: by smtp.corp.redhat.com (Postfix) id 419C835453; Tue, 14 Feb 2023 17:08:28 +0000 (UTC) Received: from himantopus.redhat.com (unknown [10.22.8.15]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 1F95C1C55A for ; Tue, 14 Feb 2023 17:08:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1676394663; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:list-id:list-help: list-unsubscribe:list-subscribe:list-post; bh=aDvQGGOF/Xaz6UxKmcDFjT4RhYF53TOUTFZvTSzg/us=; b=gpM659UL2ObzomwRF9ne/S+GORw4sosghVdCG1bYEfGmCqjcAbMb0GN9kZiAxNNE2vVYp8 l/inoB5m0xuhOosXC7gOgaV41deN/lF1JVp6K7LdM0c2ahVrFufV+v+iUuCAhQgwAh14BU ohKNCMeBUnzfqa6PQFK3Op5cyQR9SDw= X-MC-Unique: GOI5bsNUPyKw0R1w6cfcbw-1 X-Original-To: libvir-list@listman.corp.redhat.com From: Jonathon Jongsma To: libvir-list@redhat.com Subject: [libvirt PATCH v5 32/32] qemu: implement keyfile auth for ssh disk with nbdkit Date: Tue, 14 Feb 2023 11:08:19 -0600 Message-Id: <20230214170819.3143132-33-jjongsma@redhat.com> In-Reply-To: <20230214170819.3143132-1-jjongsma@redhat.com> References: <20230214170819.3143132-1-jjongsma@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.5 X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libvir-list-bounces@redhat.com Sender: "libvir-list" X-Scanned-By: MIMEDefang 3.1 on 10.11.54.8 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1676394665427100002 Content-Type: text/plain; charset="utf-8"; x-default="true" 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. The key file may be password protected, and libvirt cannot prompt the user for a password to unlock it. But if the adminstrator adds this key to an ssh agent, they can configure the disk with the path to the unix socket for the ssh agent so libvirt can pass this socket path to nbdkit and we can make use of these keys. Signed-off-by: Jonathon Jongsma --- src/conf/domain_conf.c | 36 +++++++++++++++---- src/conf/storage_source_conf.c | 2 ++ src/conf/storage_source_conf.h | 6 ++-- src/qemu/qemu_nbdkit.c | 11 ++++-- .../disk-network-ssh-key.args.disk0 | 10 ++++++ .../disk-network-ssh.args.disk2 | 9 +++++ tests/qemunbdkittest.c | 1 + .../qemuxml2argvdata/disk-network-ssh-key.xml | 33 +++++++++++++++++ 8 files changed, 97 insertions(+), 11 deletions(-) create mode 100644 tests/qemunbdkitdata/disk-network-ssh-key.args.disk0 create mode 100644 tests/qemunbdkitdata/disk-network-ssh.args.disk2 create mode 100644 tests/qemuxml2argvdata/disk-network-ssh-key.xml diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index cb9d01dc6d..d5aa92e81b 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -7214,10 +7214,21 @@ virDomainDiskSourceNetworkParse(xmlNodePtr node, return -1; } } - if (src->protocol =3D=3D VIR_STORAGE_NET_PROTOCOL_SSH && - (tmpnode =3D virXPathNode("./knownHosts", ctxt))) { - if (!(src->ssh_known_hosts_file =3D virXMLPropStringRequired(tmpno= de, "path"))) - return -1; + if (src->protocol =3D=3D VIR_STORAGE_NET_PROTOCOL_SSH) { + if ((tmpnode =3D virXPathNode("./knownHosts", ctxt))) { + if (!(src->ssh_known_hosts_file =3D virXMLPropStringRequired(t= mpnode, "path"))) + return -1; + } + if ((tmpnode =3D virXPathNode("./identity", ctxt))) { + if (!(src->ssh_keyfile =3D virXMLPropStringRequired(tmpnode, "= keyfile"))) + return -1; + + if (!(src->ssh_user =3D virXMLPropStringRequired(tmpnode, "use= rname"))) + return -1; + + /* optional ssh-agent socket location */ + src->ssh_agent =3D virXMLPropString(tmpnode, "agentsock"); + } } =20 return 0; @@ -22097,8 +22108,21 @@ virDomainDiskSourceFormatNetwork(virBuffer *attrBu= f, if (src->timeout) virBufferAsprintf(childBuf, "\n", src->= timeout); =20 - if (src->protocol =3D=3D VIR_STORAGE_NET_PROTOCOL_SSH && src->ssh_know= n_hosts_file) - virBufferAsprintf(childBuf, "\n", src->ss= h_known_hosts_file); + if (src->protocol =3D=3D VIR_STORAGE_NET_PROTOCOL_SSH) { + if (src->ssh_known_hosts_file) + virBufferAsprintf(childBuf, "\n", src= ->ssh_known_hosts_file); + if (src->ssh_keyfile) { + virBufferAddLit(childBuf, "ssh_ke= yfile); + if (src->ssh_user) + virBufferEscapeString(childBuf, " username=3D'%s'", src->s= sh_user); + if (src->ssh_agent) + virBufferEscapeString(childBuf, " agentsock=3D'%s'", src->= ssh_agent); + + virBufferAddLit(childBuf, "/>\n"); + } + } } =20 =20 diff --git a/src/conf/storage_source_conf.c b/src/conf/storage_source_conf.c index 5d60c46cfc..4b8397420b 100644 --- a/src/conf/storage_source_conf.c +++ b/src/conf/storage_source_conf.c @@ -1168,6 +1168,8 @@ virStorageSourceClear(virStorageSource *def) =20 VIR_FREE(def->ssh_user); VIR_FREE(def->ssh_known_hosts_file); + VIR_FREE(def->ssh_keyfile); + VIR_FREE(def->ssh_agent); =20 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 a2d8b1f8bd..ed4deaf58c 100644 --- a/src/conf/storage_source_conf.h +++ b/src/conf/storage_source_conf.h @@ -401,12 +401,12 @@ struct _virStorageSource { =20 bool hostcdrom; /* backing device is a cdrom */ =20 - /* passthrough variables for the ssh driver which we don't handle prop= erly */ - /* 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; + char *ssh_agent; =20 /* 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 wh= ich are used diff --git a/src/qemu/qemu_nbdkit.c b/src/qemu/qemu_nbdkit.c index dbbe71944f..811be7a583 100644 --- a/src/qemu/qemu_nbdkit.c +++ b/src/qemu/qemu_nbdkit.c @@ -1071,10 +1071,17 @@ 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_keyfil= e); + + if (proc->source->ssh_user) + virCommandAddArgPair(cmd, "user", proc->source->ssh_user); } =20 + if (proc->source->ssh_agent) + virCommandAddEnvPair(cmd, "SSH_AUTH_SOCK", proc->source->ssh_agent= ); + if (proc->source->ssh_host_key_check_disabled) virCommandAddArgPair(cmd, "verify-remote-host", "false"); =20 diff --git a/tests/qemunbdkitdata/disk-network-ssh-key.args.disk0 b/tests/q= emunbdkitdata/disk-network-ssh-key.args.disk0 new file mode 100644 index 0000000000..9842300f70 --- /dev/null +++ b/tests/qemunbdkitdata/disk-network-ssh-key.args.disk0 @@ -0,0 +1,10 @@ +SSH_AUTH_SOCK=3D/path/to/agent/socket \ +nbdkit \ +--unix /tmp/statedir-0/nbdkit-test-disk-0.socket \ +--foreground ssh \ +host=3Dexample.org \ +port=3D2222 \ +path=3Dtest2.img \ +identity=3D/path/to/id_rsa \ +user=3Dmyuser \ +known-hosts=3D/path/to/ssh_known_hosts diff --git a/tests/qemunbdkitdata/disk-network-ssh.args.disk2 b/tests/qemun= bdkitdata/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=3Dexample.org \ +port=3D2222 \ +path=3Dtest2.img \ +identity=3D/path/to/id_rsa \ +user=3Dmyuser \ +known-hosts=3D/path/to/ssh_known_hosts diff --git a/tests/qemunbdkittest.c b/tests/qemunbdkittest.c index 492077e56e..e507df6e42 100644 --- a/tests/qemunbdkittest.c +++ b/tests/qemunbdkittest.c @@ -292,6 +292,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); =20 qemuTestDriverFree(&driver); =20 diff --git a/tests/qemuxml2argvdata/disk-network-ssh-key.xml b/tests/qemuxm= l2argvdata/disk-network-ssh-key.xml new file mode 100644 index 0000000000..e8e62476d4 --- /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 + + + + + + + + + + + + + + + + + + + --=20 2.39.1