From nobody Fri Nov 21 10:12:05 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) client-ip=8.43.85.245; envelope-from=devel-bounces@lists.libvirt.org; helo=lists.libvirt.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) smtp.mailfrom=devel-bounces@lists.libvirt.org; dmarc=pass(p=reject dis=none) header.from=lists.libvirt.org ARC-Seal: i=1; a=rsa-sha256; t=1763041311; cv=none; d=zohomail.com; s=zohoarc; b=U2bOyuCj6E1rH/32Ka6QN3/nSDaEZAbh3ayfliMQDmKwESVsmh6GyKVC1N4pFsMy+MahkFXs1w0Hi199WvSlg1oJcTy/xrOVrIRr+RvtwMN03vcd7csdD95XlSbolHq//9R/3m0r9EAeo5qLX7eyWg0vH0g5m+CaUNDLjbAVq2g= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1763041311; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Owner:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:Reply-To:References:Subject:Subject:To:To:Message-Id; bh=GfMrNrn83CjwREA5Jq72wAnEHdOto5oQeIKYRrBeHM8=; b=Z852MfdRlkDs+vUnf7dQ3WFbxpx6QXrA/b4mHdC5TudpkMWbU4LK/0mj6NUfZSHm2AcvIft9KQ5aE0W71TKntXarLu6nydDDT31b90lNk4t0fMQVQOZwFRljwoXK6LZuDiwY3IxTxAAHErUX8bHoOQoSnZmt1g2vLdNKkgVzfwU= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) smtp.mailfrom=devel-bounces@lists.libvirt.org; dmarc=pass header.from= (p=reject dis=none) Return-Path: Received: from lists.libvirt.org (lists.libvirt.org [8.43.85.245]) by mx.zohomail.com with SMTPS id 1763041311340676.8380981247631; Thu, 13 Nov 2025 05:41:51 -0800 (PST) Received: by lists.libvirt.org (Postfix, from userid 993) id DDCDB446B0; Thu, 13 Nov 2025 08:41:49 -0500 (EST) Received: from [172.19.199.29] (lists.libvirt.org [8.43.85.245]) by lists.libvirt.org (Postfix) with ESMTP id 53EFC449A0; Thu, 13 Nov 2025 08:38:32 -0500 (EST) Received: by lists.libvirt.org (Postfix, from userid 993) id 5A59243E51; Thu, 13 Nov 2025 08:32:55 -0500 (EST) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (3072 bits) server-digest SHA256) (No client certificate requested) by lists.libvirt.org (Postfix) with ESMTPS id 93518441AE for ; Thu, 13 Nov 2025 08:32:49 -0500 (EST) Received: from mail-pf1-f199.google.com (mail-pf1-f199.google.com [209.85.210.199]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-569-YrLQ86DAMP-rb8B3RYfzxg-1; Thu, 13 Nov 2025 08:32:48 -0500 Received: by mail-pf1-f199.google.com with SMTP id d2e1a72fcca58-7b8ed43cd00so1007492b3a.2 for ; Thu, 13 Nov 2025 05:32:47 -0800 (PST) Received: from armenon-kvm.armenon-thinkpadp16vgen1.bengluru.csb ([49.36.110.242]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-7b927151380sm2373676b3a.38.2025.11.13.05.32.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 13 Nov 2025 05:32:44 -0800 (PST) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-26) on lists.libvirt.org X-Spam-Level: X-Spam-Status: No, score=-5.0 required=5.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED,RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED,SPF_PASS autolearn=unavailable autolearn_force=no version=4.0.1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1763040769; h=from:from: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; bh=GfMrNrn83CjwREA5Jq72wAnEHdOto5oQeIKYRrBeHM8=; b=Pz1OLznlVzcfQuUjz+6K2Ns3RuMMk/7QheXxgZJAqNemi+pIgq4KlrMqg9ULosjFF9Csbh hr9FaPMQ5bvXVaUKuBUCkh5X/rl+gZgGo/7M/LFg9pFWdAOdc2Bm+MbMYoDJ9sznBWB/Dx sHPU/ukdyl3xfBxZHcGmXehcWXt608E= X-MC-Unique: YrLQ86DAMP-rb8B3RYfzxg-1 X-Mimecast-MFC-AGG-ID: YrLQ86DAMP-rb8B3RYfzxg_1763040767 X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1763040767; x=1763645567; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=GfMrNrn83CjwREA5Jq72wAnEHdOto5oQeIKYRrBeHM8=; b=pLPRKkZhCkBIc5p5dT5C+cAcaHHe/wzkLhuQVVY0vlAgmlPzD7FqmyVnilIn/J1JMK l/HC4sY2JboPy+d5vvgz3Cx5pxL00gr9PLqA70so6kM73A7HtlNLsrAZn1r7+t2lfZiw fTZtlAZ2D7KSew0wOoaGIyMOh6JRF249Gk5JikL+rvwmd0R4/rzUGXt6qKSZSLyX1P4E zLrbwhmquYMKg9XriPWt2DZcjwPTSMlq0FkvjBZs3tV27/CYHuqfpP+9rFlRcqroqIsV +lPxK1Mqug2WU6AgfSeM6dwDBrl/VFOQ+mkNXEwTMBs7DYS9vbb/JZuMmPzO7Yoe/cJP kPKg== X-Gm-Message-State: AOJu0YxKwN+pl49eoYyddJS+G77Dx1qFiwBsg+2HOTG5YPrKpoAcJuKZ 7Ncff3MikZAkyPkUikvl9RRxvFk+lO0YlRVmN4a7EQ7LOOi/jdL3uWxbjtCxaIoXdHKmOir/OjO vQTcpTCUE2SIndhQzrlOnQ+neKK/YpzfuLdkYu4pRIyQfy55VSIqkiqhmLtKXtPAS9HuZwu87b8 AWRpR+LwI+4dyBHY+gBTyWpSW8GJJCAwRNcQSwh05jbA== X-Gm-Gg: ASbGncsi5/WC2JFhTmYisSe8+a7d7JWZqjtBtq86Swi1vuowrtnYu8Bm00zOGAtTnpZ 5/bLN/4tX8BDEJ27CYrc7AXRJ67l51m8RCDoIsVnauEuqayf1Xv8YuWN+G86fCvR7H2fkz7TuxR ofVw49V9qClrxYVayYUCkA75w6M7FucYVDp35Ra1IhmrC/uE8N74d5e+kl+4vbtSn5gMSI5BKCf Dgd11b5Nb3iEyH4RCqZ8Mw4J6SiwUkc1JvNLxT/l201xllEEB2F+j8/A5nN4WlsF4Gz1ywAvr88 7pFNa6Tlwz/VwNgS9s3vxsZCuLGnUDCvZZSmmaOWVUpGXWyFBldyRYrjG07+979x5tDzJtObA6Z DorL/OspiA/OjfSSGOddQ8hY0Ip4t+X+8eMwQphsQcLIXdN4= X-Received: by 2002:a05:6a00:929d:b0:7ab:995a:46b0 with SMTP id d2e1a72fcca58-7b7a4af9cb5mr8321233b3a.15.1763040766454; Thu, 13 Nov 2025 05:32:46 -0800 (PST) X-Google-Smtp-Source: AGHT+IE3BgzUXh2RYEkwyWMdX5LX35GiAoEwP6NCmIhxEyoeI8lUR9LepyI0Cnh1o6kwuMtzYr/waQ== X-Received: by 2002:a05:6a00:929d:b0:7ab:995a:46b0 with SMTP id d2e1a72fcca58-7b7a4af9cb5mr8321185b3a.15.1763040765880; Thu, 13 Nov 2025 05:32:45 -0800 (PST) To: devel@lists.libvirt.org Subject: [RFC 3/4] secret: Add secrets.conf configuration file and parse it Date: Thu, 13 Nov 2025 19:02:22 +0530 Message-ID: <20251113133223.32729-4-armenon@redhat.com> X-Mailer: git-send-email 2.51.1 In-Reply-To: <20251113133223.32729-1-armenon@redhat.com> References: <20251113133223.32729-1-armenon@redhat.com> MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: veSqYv3RFKxHl_11AXu61PUfrzidZJxMIZDEeXHyJUY_1763040767 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Message-ID-Hash: ZXFISEZOEIB3Y6I3PG6OSJIODI6JE2D4 X-Message-ID-Hash: ZXFISEZOEIB3Y6I3PG6OSJIODI6JE2D4 X-MailFrom: armenon@redhat.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; header-match-devel.lists.libvirt.org-0; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: Arun Menon , =?UTF-8?q?Michal=20Pr=C3=ADvozn=C3=ADk?= X-Mailman-Version: 3.3.10 Precedence: list List-Id: Development discussions about the libvirt library & tools Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: Arun Menon via Devel Reply-To: Arun Menon X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1763041321297153000 Content-Type: text/plain; charset="utf-8"; x-default="true" A new configuration file called secrets.conf is introduced to let the user configure the path to the master encryption key. This key will be used to encrypt/decrypt the secrets in libvirt. By default the path is set to the runtime directory /run/libvirt/secrets, and it is commented in the config file. The virtsecretd driver checks if the credentials are available in the CREDENTIALS_DIRECTORY. In case it is not present, then the user is expected to provide the encryption key path in secrets.conf Add logic to parse the encryption key file and store the key. When systemd will start the secrets driver, it will read the secret.conf file and check if encrypt_data flag is set to 1. In that case, the secrets will be stored in encrypted format on the disk. The encryption and decrypti= on logic will be added in the subsequent patches. Signed-off-by: Arun Menon --- libvirt.spec.in | 1 + src/secret/meson.build | 7 +++ src/secret/secret_driver.c | 96 ++++++++++++++++++++++++++++++++++++++ src/secret/secrets.conf.in | 14 ++++++ 4 files changed, 118 insertions(+) create mode 100644 src/secret/secrets.conf.in diff --git a/libvirt.spec.in b/libvirt.spec.in index 79738bd7bb..f27247b7c1 100644 --- a/libvirt.spec.in +++ b/libvirt.spec.in @@ -2246,6 +2246,7 @@ exit 0 %config(noreplace) %{_sysconfdir}/libvirt/virtsecretd.conf %{_datadir}/augeas/lenses/virtsecretd.aug %{_datadir}/augeas/lenses/tests/test_virtsecretd.aug +%config(noreplace) %{_sysconfdir}/libvirt/secrets.conf %{_unitdir}/virtsecretd.service %{_unitdir}/virtsecretd.socket %{_unitdir}/virtsecretd-ro.socket diff --git a/src/secret/meson.build b/src/secret/meson.build index 3b859ea7b4..a211ffed83 100644 --- a/src/secret/meson.build +++ b/src/secret/meson.build @@ -27,6 +27,13 @@ if conf.has('WITH_SECRETS') ], } =20 + secrets_conf =3D configure_file( + input: 'secrets.conf.in', + output: 'secrets.conf', + copy: true + ) + virt_conf_files +=3D secrets_conf + virt_daemon_confs +=3D { 'name': 'virtsecretd', } diff --git a/src/secret/secret_driver.c b/src/secret/secret_driver.c index 04c3ca49f1..0b415e5ef3 100644 --- a/src/secret/secret_driver.c +++ b/src/secret/secret_driver.c @@ -42,6 +42,7 @@ #include "secret_event.h" #include "virutil.h" #include "virinhibitor.h" +#include "virfile.h" =20 #define VIR_FROM_THIS VIR_FROM_SECRET =20 @@ -70,6 +71,17 @@ struct _virSecretDriverState { =20 /* Immutable pointer, self-locking APIs */ virInhibitor *inhibitor; + + /* master encryption key value from secret.conf file */ + char *masterKeyPath; + + /* Indicates if the secrets are encrypted or not. 0 if not encrypted + * and 1 if encrypted. + */ + int encrypt_data; + + unsigned char* masterKey; + size_t masterKeyLen; }; =20 static virSecretDriverState *driver; @@ -307,6 +319,44 @@ secretGetXMLDesc(virSecretPtr secret, return ret; } =20 +static bool secretGetMasterKey(uint8_t **masterKey, size_t *masterKeyLen) +{ + int fd =3D -1; + struct stat st; + + if ((fd =3D open(driver->masterKeyPath, O_RDONLY)) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, _("Cannot open master key f= ile '%1$s'"), + driver->masterKeyPath); + return false; + } + if (fstat(fd, &st) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, _("Cannot stat master key f= ile '%1$s'"), + driver->masterKeyPath); + VIR_FORCE_CLOSE(fd); + return false; + } + *masterKeyLen =3D st.st_size; + if (*masterKeyLen =3D=3D 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, _("Master encryption key fi= le %1$s is empty"), + driver->masterKeyPath); + VIR_FORCE_CLOSE(fd); + return false; + } + *masterKey =3D g_new0(uint8_t, *masterKeyLen); + if (saferead(fd, &masterKey, *masterKeyLen) !=3D *masterKeyLen) { + virReportError(VIR_ERR_INTERNAL_ERROR, _("Cannot read master key f= ile '%1$s'"), + driver->masterKeyPath); + VIR_FORCE_CLOSE(fd); + return false; + } + VIR_FORCE_CLOSE(fd); + if (*masterKeyLen < 32) { + virReportError(VIR_ERR_INTERNAL_ERROR, _("Master encryption key fi= le %1$s must be atleast 32 bytes"), + driver->masterKeyPath); + return false; + } + return true; +} =20 static int secretSetValue(virSecretPtr secret, @@ -482,6 +532,10 @@ secretStateInitialize(bool privileged, void *opaque) { VIR_LOCK_GUARD lock =3D virLockGuardLock(&mutex); + g_autofree char *secretsconf =3D NULL; + g_autofree char *credentials_directory =3D NULL; + g_autofree char *master_encryption_key_path =3D NULL; + g_autoptr(virConf) conf =3D NULL; =20 driver =3D g_new0(virSecretDriverState, 1); =20 @@ -537,6 +591,48 @@ secretStateInitialize(bool privileged, if (virSecretLoadAllConfigs(driver->secrets, driver->configDir) < 0) goto error; =20 + secretsconf =3D g_strdup_printf("%s/libvirt/secrets.conf", SYSCONFDIR); + credentials_directory =3D getenv("CREDENTIALS_DIRECTORY"); + + if (credentials_directory) { + VIR_DEBUG("Using credentials directory from environment: %s", + credentials_directory); + master_encryption_key_path =3D g_strdup_printf("%s/master-encrypti= on-key", credentials_directory); + if (access(master_encryption_key_path, R_OK) =3D=3D 0) { + driver->masterKeyPath =3D g_strdup(master_encryption_key_path); + } + } else if (access(secretsconf, R_OK) =3D=3D 0) { + if (!(conf =3D virConfReadFile(secretsconf, 0))) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Failed to read secrets.conf from %1$s"), + secretsconf); + goto error; + } + + if (virConfGetValueString(conf, "master_encryption_key", &driver->= masterKeyPath) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Failed to get master_encryption_key from %1$= s"), + secretsconf); + goto error; + } + } else { + VIR_DEBUG("No secrets configuration found %s, skipping", driver->c= onfigDir); + driver->masterKeyPath =3D NULL; + driver->masterKeyLen =3D 0; + } + if (driver->masterKeyPath) { + if (!secretGetMasterKey(&driver->masterKey, &driver->masterKeyLen)= ) { + goto error; + } + VIR_DEBUG("Master encryption key loaded from %s", driver->masterKe= yPath); + VIR_DEBUG("Master encryption key length: %zu bytes", driver->maste= rKeyLen); + } + if (virConfGetValueInt(conf, "encrypt_data", &driver->encrypt_data) < = 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Failed to get encrypt_data from %1$s"), + secretsconf); + goto error; + } return VIR_DRV_STATE_INIT_COMPLETE; =20 error: diff --git a/src/secret/secrets.conf.in b/src/secret/secrets.conf.in new file mode 100644 index 0000000000..80bb9654ce --- /dev/null +++ b/src/secret/secrets.conf.in @@ -0,0 +1,14 @@ +# +# Master configuration file for the secrets driver. +# + +# The master encryption key is used to override default master encryption +# key path. The user can create an encryption key and set the master_encry= ption_key +# to the path on which it resides. +# The key must be atleast 32-bytes long. +# +# master_encryption_key =3D "/run/libvirt/secrets/master.key" +# +# The encrypt_data setting is used to indicate if the encryption is on or = off. +# 0 indicates off and 1 indicates on. By default it is set to on. +encrypt_data =3D 1 --=20 2.51.1