From nobody Mon Feb 9 19:37:52 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of redhat.com designates 170.10.129.124 as permitted sender) client-ip=170.10.129.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.129.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=1693518060; cv=none; d=zohomail.com; s=zohoarc; b=GuSz85UzHlRU9gnU8TiHVODYucTIIO8Hdv/W7fpeiOxjLdZJ+TcKulPdg3eLVChDuSrZu68DC0yoMd/JTe/dIksK2x81J8qZ/5AL/Bz0fUsTqhbiXaJ5iorul2kQ82714gA8Su6SeWRgiXA0AHsAowU/LguWvVsIA1Az+GZFg0M= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1693518060; h=Content-Type:Content-Transfer-Encoding:Cc: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=egP60J4V42txkea5CXaqoXowTj2iuARD0EZ9lAmkbTY=; b=B0UeWlJNg3CxBhVf+5ygDa0ZpRvksdzK2fNVBwu6FnXXP9HKvh8tFcVL2BqbquIQw/GJzHm1lVqr8JON9WZxo/kv7Hq62fdWqyWyDxohJ3XR5lrKDS+LeuxlcRk2WA9PBVqxBIMqNR4eoboU5g0HIuvntgpDphz6TPLfg+wiY2Q= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 170.10.129.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.129.124]) by mx.zohomail.com with SMTPS id 1693518060724529.8821450493155; Thu, 31 Aug 2023 14:41:00 -0700 (PDT) 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-473-v5hdZCpMOiywa_Bkj54WJg-1; Thu, 31 Aug 2023 17:40:55 -0400 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 9587C80D1A6; Thu, 31 Aug 2023 21:40:51 +0000 (UTC) Received: from mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com [10.30.29.100]) by smtp.corp.redhat.com (Postfix) with ESMTP id 80AE040C207A; Thu, 31 Aug 2023 21:40:51 +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 AE1AB19451F8; Thu, 31 Aug 2023 21:40:43 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx09.intmail.prod.int.rdu2.redhat.com [10.11.54.9]) by mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (Postfix) with ESMTP id C30141949751 for ; Thu, 31 Aug 2023 21:40:27 +0000 (UTC) Received: by smtp.corp.redhat.com (Postfix) id AD05E492C3A; Thu, 31 Aug 2023 21:40:27 +0000 (UTC) Received: from himantopus.redhat.com (unknown [10.22.17.68]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 821CF492C13; Thu, 31 Aug 2023 21:40:27 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1693518059; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc: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=egP60J4V42txkea5CXaqoXowTj2iuARD0EZ9lAmkbTY=; b=gaqe5Tp5k8qf5xbGV2+Y5DfsLQPAjmfv980oBwt1wOxJ9jPSmLVsbE7CJTxhpzWAm2KN5x 1hKuzD0vwYhFy5v+xi9qvnI3l5qQihaGyAULycWNtUFOp9F40M/fCCxEfg6X19wotYG1ql GRgcV9tpeBPrGPAyilcwnqjUZ14A3VM= X-MC-Unique: v5hdZCpMOiywa_Bkj54WJg-1 X-Original-To: libvir-list@listman.corp.redhat.com From: Jonathon Jongsma To: libvir-list@redhat.com Subject: [libvirt PATCH v8 35/37] qemu: implement ssh-agent auth for ssh disks with nbdkit Date: Thu, 31 Aug 2023 16:40:15 -0500 Message-ID: <20230831214017.1536388-36-jjongsma@redhat.com> In-Reply-To: <20230831214017.1536388-1-jjongsma@redhat.com> References: <20230831214017.1536388-1-jjongsma@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.9 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: , Cc: Peter Krempa Errors-To: libvir-list-bounces@redhat.com Sender: "libvir-list" X-Scanned-By: MIMEDefang 3.1 on 10.11.54.1 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: 1693518063034100007 Content-Type: text/plain; charset="utf-8"; x-default="true" It's not possible to use password-protected ssh keys directly with libvirt because libvirt doesn't have any way to prompt a user for the password. To accomodate password-protected key files, an administrator can add these keys to an ssh agent and then configure the domain with the path to the ssh-agent socket. Note that this requires an administrator or management app to configure the ssh-agent with an appropriate socket path and add the necessary keys to it. In addition, it does not currently work with selinux enabled. The ssh-agent socket would need a label that libvirt would be allowed to access rather than unconfined_t. Signed-off-by: Jonathon Jongsma Reviewed-by: Peter Krempa --- src/conf/domain_conf.c | 14 ++++++++++++-- src/conf/storage_source_conf.c | 2 ++ src/conf/storage_source_conf.h | 1 + src/qemu/qemu_nbdkit.c | 10 ++++++++++ .../disk-network-ssh-key.args.disk0 | 6 +++--- .../disk-network-ssh-key.args.disk1 | 9 +++++++++ tests/qemuxml2argvdata/disk-network-ssh-key.xml | 17 ++++++++++++++--- 7 files changed, 51 insertions(+), 8 deletions(-) create mode 100644 tests/qemunbdkitdata/disk-network-ssh-key.args.disk1 diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 929e115bce..398f40d2be 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -7277,8 +7277,17 @@ virDomainDiskSourceNetworkParse(xmlNodePtr node, if (!(src->ssh_user =3D virXMLPropStringRequired(tmpnode, "use= rname"))) return -1; =20 - if (!(src->ssh_keyfile =3D virXMLPropStringRequired(tmpnode, "= keyfile"))) + /* optional path to an ssh key file */ + src->ssh_keyfile =3D virXMLPropString(tmpnode, "keyfile"); + + /* optional ssh-agent socket location */ + src->ssh_agent =3D virXMLPropString(tmpnode, "agentsock"); + if (!src->ssh_keyfile && !src->ssh_agent) { + virReportError(VIR_ERR_XML_ERROR, + _("element '%1$s' requires either 'keyfile'= or 'agentsock' attribute"), + tmpnode->name); return -1; + } } } =20 @@ -22291,11 +22300,12 @@ virDomainDiskSourceFormatNetwork(virBuffer *attrB= uf, if (src->protocol =3D=3D VIR_STORAGE_NET_PROTOCOL_SSH) { if (src->ssh_known_hosts_file) virBufferEscapeString(childBuf, "\n",= src->ssh_known_hosts_file); - if (src->ssh_keyfile) { + if (src->ssh_keyfile || src->ssh_agent) { virBufferAddLit(childBuf, "ssh_u= ser); virBufferEscapeString(childBuf, " keyfile=3D'%s'", src->ssh_ke= yfile); + virBufferEscapeString(childBuf, " agentsock=3D'%s'", src->ssh_= agent); =20 virBufferAddLit(childBuf, "/>\n"); } diff --git a/src/conf/storage_source_conf.c b/src/conf/storage_source_conf.c index ce9c1f66c2..cafa031dfe 100644 --- a/src/conf/storage_source_conf.c +++ b/src/conf/storage_source_conf.c @@ -897,6 +897,7 @@ virStorageSourceCopy(const virStorageSource *src, def->ssh_user =3D g_strdup(src->ssh_user); def->ssh_known_hosts_file =3D g_strdup(src->ssh_known_hosts_file); def->ssh_keyfile =3D g_strdup(src->ssh_keyfile); + def->ssh_agent =3D g_strdup(src->ssh_agent); =20 def->nfs_user =3D g_strdup(src->nfs_user); def->nfs_group =3D g_strdup(src->nfs_group); @@ -1174,6 +1175,7 @@ virStorageSourceClear(virStorageSource *def) 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 8c805664af..061faa66cb 100644 --- a/src/conf/storage_source_conf.h +++ b/src/conf/storage_source_conf.h @@ -411,6 +411,7 @@ struct _virStorageSource { bool ssh_host_key_check_disabled; 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 0a6c7962b0..66b09cd240 100644 --- a/src/qemu/qemu_nbdkit.c +++ b/src/qemu/qemu_nbdkit.c @@ -1057,6 +1057,9 @@ qemuNbdkitProcessBuildCommandSSH(qemuNbdkitProcess *p= roc, 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 @@ -1179,6 +1182,10 @@ qemuNbdkitProcessStart(qemuNbdkitProcess *proc, qemuSecurityDomainSetPathLabel(driver, vm, proc->source->ssh_keyfi= le, false) < 0) goto error; =20 + if (proc->source->ssh_agent && + qemuSecurityDomainSetPathLabel(driver, vm, proc->source->ssh_agent= , false) < 0) + goto error; + if (proc->source->ssh_known_hosts_file && qemuSecurityDomainSetPathLabel(driver, vm, proc->source->ssh_known= _hosts_file, false) < 0) goto error; @@ -1267,6 +1274,9 @@ qemuNbdkitProcessStop(qemuNbdkitProcess *proc, if (proc->source->ssh_keyfile) qemuSecurityDomainRestorePathLabel(driver, vm, proc->source->ssh_k= eyfile); =20 + if (proc->source->ssh_agent) + qemuSecurityDomainRestorePathLabel(driver, vm, proc->source->ssh_a= gent); + if (proc->pid < 0) return 0; =20 diff --git a/tests/qemunbdkitdata/disk-network-ssh-key.args.disk0 b/tests/q= emunbdkitdata/disk-network-ssh-key.args.disk0 index 0b52bfe0fb..f627700490 100644 --- a/tests/qemunbdkitdata/disk-network-ssh-key.args.disk0 +++ b/tests/qemunbdkitdata/disk-network-ssh-key.args.disk0 @@ -1,9 +1,9 @@ +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=3Dtest.img \ -identity=3D/path/to/id_rsa \ +path=3Dtest1.img \ user=3Dmyuser \ -known-hosts=3D/path/to/ssh_known_hosts +known-hosts=3D/path/to/ssh_known_hosts1 diff --git a/tests/qemunbdkitdata/disk-network-ssh-key.args.disk1 b/tests/q= emunbdkitdata/disk-network-ssh-key.args.disk1 new file mode 100644 index 0000000000..80df9c30c6 --- /dev/null +++ b/tests/qemunbdkitdata/disk-network-ssh-key.args.disk1 @@ -0,0 +1,9 @@ +nbdkit \ +--unix /tmp/statedir-1/nbdkit-test-disk-1.socket \ +--foreground ssh \ +host=3Dexample.org \ +port=3D2222 \ +path=3Dtest2.img \ +identity=3D/path/to/id_rsa \ +user=3Dmyuser2 \ +known-hosts=3D/path/to/ssh_known_hosts2 diff --git a/tests/qemuxml2argvdata/disk-network-ssh-key.xml b/tests/qemuxm= l2argvdata/disk-network-ssh-key.xml index 81b92231fa..fda01e7e68 100644 --- a/tests/qemuxml2argvdata/disk-network-ssh-key.xml +++ b/tests/qemuxml2argvdata/disk-network-ssh-key.xml @@ -15,12 +15,23 @@ - + - - + + + + + + + + + + + + + --=20 2.41.0