From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from gate001.proxmox.com (gate001.proxmox.com [IPv6:2a0f:8001:1:32::40]) by lore.proxmox.com (Postfix) with ESMTPS id B87DC1FF129 for ; Thu, 06 Aug 2026 17:23:46 +0200 (CEST) Received: from gate001.proxmox.com (localhost.localdomain [127.0.0.1]) by gate001.proxmox.com (Proxmox) with ESMTP id 890D0214D6; Thu, 06 Aug 2026 17:23:46 +0200 (CEST) Date: Thu, 06 Aug 2026 17:23:38 +0200 From: Fabian =?iso-8859-1?q?Gr=FCnbichler?= Subject: Re: [PATCH datacenter-manager v2 07/16] cli/api-types: move Fingerprint to common api type crate To: pdm-devel@lists.proxmox.com, Shannon Sterz References: <20260805131838.254723-2-s.sterz@proxmox.com> <20260805131838.254723-9-s.sterz@proxmox.com> In-Reply-To: <20260805131838.254723-9-s.sterz@proxmox.com> MIME-Version: 1.0 User-Agent: astroid/0.17.0 (https://github.com/astroidmail/astroid) Message-Id: <1786029069.14qi906cuy.astroid@yuna.none> Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Bm-Milter-Handled: 55990f41-d878-4baa-be0a-ee34c49e34d2 X-Bm-Transport-Timestamp: 1786029806191 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.094 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: 4OYSEPHYFIBPGVXDI64ZKFQJXPVRCEBH X-Message-ID-Hash: 4OYSEPHYFIBPGVXDI64ZKFQJXPVRCEBH X-MailFrom: f.gruenbichler@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 Datacenter Manager development discussion List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: On August 5, 2026 3:18 pm, Shannon Sterz wrote: > this type is more generally useful when working with certificates, so > move it to the common pdm api types. in proxmox.git we have: pbs_api_types::remote pbs_api_types::crypto::Fingerprint (accidentally the same format) proxmox_acme_api::types::CertificateInfo.Fingerprint (String) proxmox_node_status::types::NodeInformation.Fingerprint (String) proxmox_client::client::TlsOptions::parse_fingerprint (&str -> Vec) in proxmox-backup.git we have (at least): remote config fingerprint via pbs_api_types HttpClient fingerprint in pbs-client could we please move this into a (more) central place and use it everywhere= ;) >=20 > Signed-off-by: Shannon Sterz > --- > cli/client/src/env/fingerprint_cache.rs | 77 +----------------------- > cli/client/src/env/mod.rs | 2 +- > lib/pdm-api-types/Cargo.toml | 1 + > lib/pdm-api-types/src/fingerprint.rs | 78 +++++++++++++++++++++++++ > lib/pdm-api-types/src/lib.rs | 3 + > 5 files changed, 84 insertions(+), 77 deletions(-) > create mode 100644 lib/pdm-api-types/src/fingerprint.rs >=20 > diff --git a/cli/client/src/env/fingerprint_cache.rs b/cli/client/src/env= /fingerprint_cache.rs > index cc103347..5d6eb88a 100644 > --- a/cli/client/src/env/fingerprint_cache.rs > +++ b/cli/client/src/env/fingerprint_cache.rs > @@ -6,82 +6,7 @@ use anyhow::{Error, bail, format_err}; > use openssl::hash::MessageDigest; > use openssl::x509::X509StoreContextRef; > =20 > -/// A sha256 fingerprint. > -// NOTE: The difference to ConfigDigest is that this also allows colons = between bytes when parsing. > -// Also the API type's description is different. > -#[derive(Clone, Debug, Eq, PartialEq)] > -pub struct Fingerprint([u8; 32]); > -serde_plain::derive_deserialize_from_fromstr!(Fingerprint, "valid sha256= fingerprint"); > -serde_plain::derive_serialize_from_display!(Fingerprint); > - > -impl From<[u8; 32]> for Fingerprint { > - #[inline] > - fn from(fp: [u8; 32]) -> Self { > - Self(fp) > - } > -} > - > -impl From for [u8; 32] { > - #[inline] > - fn from(fp: Fingerprint) -> Self { > - fp.0 > - } > -} > - > -impl TryFrom<&[u8]> for Fingerprint { > - type Error =3D std::array::TryFromSliceError; > - > - fn try_from(slice: &[u8]) -> Result { > - Ok(Self(slice.try_into()?)) > - } > -} > - > -impl AsRef<[u8]> for Fingerprint { > - fn as_ref(&self) -> &[u8] { > - &self.0 > - } > -} > - > -impl AsRef<[u8; 32]> for Fingerprint { > - fn as_ref(&self) -> &[u8; 32] { > - &self.0 > - } > -} > - > -impl std::ops::Deref for Fingerprint { > - type Target =3D [u8; 32]; > - > - fn deref(&self) -> &[u8; 32] { > - &self.0 > - } > -} > - > -impl std::ops::DerefMut for Fingerprint { > - fn deref_mut(&mut self) -> &mut [u8; 32] { > - &mut self.0 > - } > -} > - > -impl std::fmt::Display for Fingerprint { > - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { > - write!(f, "{:02x}", self[0])?; > - for b in &self[1..] { > - write!(f, ":{b:02x}")?; > - } > - Ok(()) > - } > -} > - > -impl std::str::FromStr for Fingerprint { > - type Err =3D Error; > - > - fn from_str(s: &str) -> Result { > - let s =3D s.replace(':', ""); > - let mut fp =3D [0u8; 32]; > - hex::decode_to_slice(s, &mut fp)?; > - Ok(Fingerprint(fp)) > - } > -} > +use pdm_api_types::Fingerprint; > =20 > pub struct FingerprintCache { > pub interactive: bool, > diff --git a/cli/client/src/env/mod.rs b/cli/client/src/env/mod.rs > index 44a9388f..97d8e594 100644 > --- a/cli/client/src/env/mod.rs > +++ b/cli/client/src/env/mod.rs > @@ -11,6 +11,7 @@ use http::Uri; > use openssl::x509; > use serde::{Deserialize, Serialize}; > =20 > +pub use pdm_api_types::Fingerprint; > use proxmox_auth_api::types::Userid; > use proxmox_client::TfaChallenge; > use proxmox_schema::api; > @@ -19,7 +20,6 @@ use crate::XDG; > use crate::config::{FormatArgs, PdmConnectArgs}; > =20 > mod fingerprint_cache; > -pub use fingerprint_cache::Fingerprint; > use fingerprint_cache::FingerprintCache; > =20 > macro_rules! xdg_path { > diff --git a/lib/pdm-api-types/Cargo.toml b/lib/pdm-api-types/Cargo.toml > index f9e3d07e..e3a40934 100644 > --- a/lib/pdm-api-types/Cargo.toml > +++ b/lib/pdm-api-types/Cargo.toml > @@ -8,6 +8,7 @@ description =3D "general API type helpers for PDM" > [dependencies] > anyhow.workspace =3D true > const_format.workspace =3D true > +hex.workspace =3D true > http.workspace =3D true > regex.workspace =3D true > serde.workspace =3D true > diff --git a/lib/pdm-api-types/src/fingerprint.rs b/lib/pdm-api-types/src= /fingerprint.rs > new file mode 100644 > index 00000000..ee7f9229 > --- /dev/null > +++ b/lib/pdm-api-types/src/fingerprint.rs > @@ -0,0 +1,78 @@ > +use anyhow::Error; > + > +/// A sha256 fingerprint. > +// NOTE: The difference to ConfigDigest is that this also allows colons = between bytes when parsing. > +// Also the API type's description is different. > +#[derive(Clone, Debug, Eq, PartialEq)] > +pub struct Fingerprint([u8; 32]); > +serde_plain::derive_deserialize_from_fromstr!(Fingerprint, "valid sha256= fingerprint"); > +serde_plain::derive_serialize_from_display!(Fingerprint); > + > +impl From<[u8; 32]> for Fingerprint { > + #[inline] > + fn from(fp: [u8; 32]) -> Self { > + Self(fp) > + } > +} > + > +impl From for [u8; 32] { > + #[inline] > + fn from(fp: Fingerprint) -> Self { > + fp.0 > + } > +} > + > +impl TryFrom<&[u8]> for Fingerprint { > + type Error =3D std::array::TryFromSliceError; > + > + fn try_from(slice: &[u8]) -> Result { > + Ok(Self(slice.try_into()?)) > + } > +} > + > +impl AsRef<[u8]> for Fingerprint { > + fn as_ref(&self) -> &[u8] { > + &self.0 > + } > +} > + > +impl AsRef<[u8; 32]> for Fingerprint { > + fn as_ref(&self) -> &[u8; 32] { > + &self.0 > + } > +} > + > +impl std::ops::Deref for Fingerprint { > + type Target =3D [u8; 32]; > + > + fn deref(&self) -> &[u8; 32] { > + &self.0 > + } > +} > + > +impl std::ops::DerefMut for Fingerprint { > + fn deref_mut(&mut self) -> &mut [u8; 32] { > + &mut self.0 > + } > +} > + > +impl std::fmt::Display for Fingerprint { > + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { > + write!(f, "{:02x}", self[0])?; > + for b in &self[1..] { > + write!(f, ":{b:02x}")?; > + } > + Ok(()) > + } > +} > + > +impl std::str::FromStr for Fingerprint { > + type Err =3D Error; > + > + fn from_str(s: &str) -> Result { > + let s =3D s.replace(':', ""); > + let mut fp =3D [0u8; 32]; > + hex::decode_to_slice(s, &mut fp)?; > + Ok(Fingerprint(fp)) > + } > +} > diff --git a/lib/pdm-api-types/src/lib.rs b/lib/pdm-api-types/src/lib.rs > index 89d1b4ad..4d6ff98c 100644 > --- a/lib/pdm-api-types/src/lib.rs > +++ b/lib/pdm-api-types/src/lib.rs > @@ -106,6 +106,9 @@ pub mod ceph; > =20 > pub mod firewall; > =20 > +mod fingerprint; > +pub use fingerprint::Fingerprint; > + > pub mod remotes; > =20 > pub mod remote_updates; > --=20 > 2.47.3 >=20 >=20 >=20 >=20 >=20 >=20