From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from gate001.proxmox.com (gate001.proxmox.com [45.144.208.40]) by lore.proxmox.com (Postfix) with ESMTPS id 12B241FF0EF for ; Thu, 30 Jul 2026 15:32:21 +0200 (CEST) Received: from gate001.proxmox.com (localhost.localdomain [127.0.0.1]) by gate001.proxmox.com (Proxmox) with ESMTP id 62BF9214CC; Thu, 30 Jul 2026 15:32:13 +0200 (CEST) From: Shannon Sterz To: pbs-devel@lists.proxmox.com Subject: [PATCH proxmox-backup 05/16] config: use proxmox_tls_certificates for generating self-signed certificates Date: Thu, 30 Jul 2026 15:31:47 +0200 Message-ID: <20260730133158.418015-6-s.sterz@proxmox.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260730133158.418015-1-s.sterz@proxmox.com> References: <20260730133158.418015-1-s.sterz@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Bm-Milter-Handled: 55990f41-d878-4baa-be0a-ee34c49e34d2 X-Bm-Transport-Timestamp: 1785418313272 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.147 Adjusted score from AWL reputation of From: address DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment (newer systems) RCVD_IN_DNSWL_LOW -0.7 Sender listed at https://www.dnswl.org/, low trust SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record Message-ID-Hash: E7RPZIZYBJWSUGKIVIT6IS3FY5EIV5QC X-Message-ID-Hash: E7RPZIZYBJWSUGKIVIT6IS3FY5EIV5QC X-MailFrom: s.sterz@proxmox.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header X-Mailman-Version: 3.3.10 Precedence: list List-Id: Proxmox Backup Server development discussion List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: to avoid duplicating almost identical code here, re-use the version from `proxmox_tls_certificates::create_self_signed_cert`. for `days_valid` specify `None` to opt into the default of 3650 days. Signed-off-by: Shannon Sterz --- Cargo.toml | 3 ++ debian/control | 2 + src/config/mod.rs | 94 ++++------------------------------------------- 3 files changed, 13 insertions(+), 86 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a2dcf85c3..df5f8942c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -97,6 +97,7 @@ proxmox-sys = "1" proxmox-systemd = "1.0.1" proxmox-tfa = { version = "6.0.3", features = [ "api", "api-types" ] } proxmox-time = "2" +proxmox-tls-certificates = { version = "1", features = [ "impl" ] } proxmox-upgrade-checks = "1" proxmox-uuid = { version = "1", features = [ "serde" ] } proxmox-worker-task = "1" @@ -255,6 +256,7 @@ proxmox-sys = { workspace = true, features = [ "timer" ] } proxmox-systemd.workspace = true proxmox-tfa.workspace = true proxmox-time.workspace = true +proxmox-tls-certificates.workspace = true proxmox-upgrade-checks.workspace = true proxmox-uuid.workspace = true proxmox-worker-task.workspace = true @@ -325,6 +327,7 @@ proxmox-rrd-api-types.workspace = true #proxmox-systemd = { path = "../proxmox/proxmox-systemd" } #proxmox-tfa = { path = "../proxmox/proxmox-tfa" } #proxmox-time = { path = "../proxmox/proxmox-time" } +#proxmox-tls-certificates = { path = "../proxmox/proxmox-tls-certificates" } #proxmox-upgrade-checks = { path = "../proxmox/proxmox-upgrade-checks" } #proxmox-uuid = { path = "../proxmox/proxmox-uuid" } #proxmox-worker-task = { path = "../proxmox/proxmox-worker-task" } diff --git a/debian/control b/debian/control index d8dcabdb7..8b9607fff 100644 --- a/debian/control +++ b/debian/control @@ -132,6 +132,8 @@ Build-Depends: debhelper (>= 12~), librust-proxmox-tfa-6+api-types-dev (>= 6.0.3-~~), librust-proxmox-tfa-6+default-dev (>= 6.0.3-~~), librust-proxmox-time-2+default-dev, + librust-proxmox-tls-certificates-1+default-dev, + librust-proxmox-tls-certificates-1+impl-dev, librust-proxmox-upgrade-checks-1+default-dev, librust-proxmox-uuid-1+default-dev, librust-proxmox-uuid-1+serde-dev, diff --git a/src/config/mod.rs b/src/config/mod.rs index 98683186e..bbca5a9af 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -5,9 +5,6 @@ use anyhow::{Error, bail, format_err}; use nix::sys::stat::Mode; -use openssl::pkey::PKey; -use openssl::rsa::Rsa; -use openssl::x509::X509Builder; use std::path::Path; use proxmox_lang::try_block; @@ -90,92 +87,17 @@ pub fn update_self_signed_cert(force: bool) -> Result<(), Error> { if key_path.exists() && cert_path.exists() && !force { return Ok(()); } - - let rsa = Rsa::generate(4096).unwrap(); - - let priv_pem = rsa.private_key_to_pem()?; - - let mut x509 = X509Builder::new()?; - - x509.set_version(2)?; - - let today = openssl::asn1::Asn1Time::days_from_now(0)?; - x509.set_not_before(&today)?; - let expire = openssl::asn1::Asn1Time::days_from_now(365 * 1000)?; - x509.set_not_after(&expire)?; - - let nodename = proxmox_sys::nodename(); - let mut fqdn = nodename.to_owned(); - let resolv_conf = crate::api2::node::dns::read_etc_resolv_conf()?; - if let Some(search) = resolv_conf["search"].as_str() { - fqdn.push('.'); - fqdn.push_str(search); - } - // we try to generate an unique 'subject' to avoid browser problems - //(reused serial numbers, ..) - let uuid = proxmox_uuid::Uuid::generate(); + let (priv_key, cert) = proxmox_tls_certificates::create_self_signed_cert( + "Proxmox Backup Server", + proxmox_sys::nodename(), + resolv_conf["search"].as_str(), + None, + )?; - let mut subject_name = openssl::x509::X509NameBuilder::new()?; - subject_name.append_entry_by_text("O", "Proxmox Backup Server")?; - subject_name.append_entry_by_text("OU", &format!("{uuid:X}"))?; - subject_name.append_entry_by_text("CN", &fqdn)?; - let subject_name = subject_name.build(); - - x509.set_subject_name(&subject_name)?; - x509.set_issuer_name(&subject_name)?; - - let bc = openssl::x509::extension::BasicConstraints::new(); // CA = false - let bc = bc.build()?; - x509.append_extension(bc)?; - - let usage = openssl::x509::extension::ExtendedKeyUsage::new() - .server_auth() - .build()?; - x509.append_extension(usage)?; - - let context = x509.x509v3_context(None, None); - - let mut alt_names = openssl::x509::extension::SubjectAlternativeName::new(); - - alt_names.ip("127.0.0.1"); - alt_names.ip("::1"); - - alt_names.dns("localhost"); - - if nodename != "localhost" { - alt_names.dns(nodename); - } - if nodename != fqdn { - alt_names.dns(&fqdn); - } - - let alt_names = alt_names.build(&context)?; - - x509.append_extension(alt_names)?; - - let pub_pem = rsa.public_key_to_pem()?; - let pubkey = PKey::public_key_from_pem(&pub_pem)?; - - x509.set_pubkey(&pubkey)?; - - let context = x509.x509v3_context(None, None); - let ext = openssl::x509::extension::SubjectKeyIdentifier::new().build(&context)?; - x509.append_extension(ext)?; - - let context = x509.x509v3_context(None, None); - let ext = openssl::x509::extension::AuthorityKeyIdentifier::new() - .keyid(true) - .build(&context)?; - x509.append_extension(ext)?; - - let privkey = PKey::from_rsa(rsa)?; - - x509.sign(&privkey, openssl::hash::MessageDigest::sha256())?; - - let x509 = x509.build(); - let cert_pem = x509.to_pem()?; + let cert_pem = cert.to_pem()?; + let priv_pem = priv_key.private_key_to_pem_pkcs8()?; set_proxy_certificate(&cert_pem, &priv_pem)?; -- 2.47.3