From: "Fabian Grünbichler" <f.gruenbichler@proxmox.com>
To: pdm-devel@lists.proxmox.com, Shannon Sterz <s.sterz@proxmox.com>
Subject: Re: [PATCH datacenter-manager v2 07/16] cli/api-types: move Fingerprint to common api type crate
Date: Thu, 06 Aug 2026 17:23:38 +0200 [thread overview]
Message-ID: <1786029069.14qi906cuy.astroid@yuna.none> (raw)
In-Reply-To: <20260805131838.254723-9-s.sterz@proxmox.com>
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<u8>)
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 ;)
>
> Signed-off-by: Shannon Sterz <s.sterz@proxmox.com>
> ---
> 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
>
> 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;
>
> -/// 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<Fingerprint> for [u8; 32] {
> - #[inline]
> - fn from(fp: Fingerprint) -> Self {
> - fp.0
> - }
> -}
> -
> -impl TryFrom<&[u8]> for Fingerprint {
> - type Error = std::array::TryFromSliceError;
> -
> - fn try_from(slice: &[u8]) -> Result<Self, Self::Error> {
> - 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 = [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 = Error;
> -
> - fn from_str(s: &str) -> Result<Self, Error> {
> - let s = s.replace(':', "");
> - let mut fp = [0u8; 32];
> - hex::decode_to_slice(s, &mut fp)?;
> - Ok(Fingerprint(fp))
> - }
> -}
> +use pdm_api_types::Fingerprint;
>
> 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};
>
> +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};
>
> mod fingerprint_cache;
> -pub use fingerprint_cache::Fingerprint;
> use fingerprint_cache::FingerprintCache;
>
> 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 = "general API type helpers for PDM"
> [dependencies]
> anyhow.workspace = true
> const_format.workspace = true
> +hex.workspace = true
> http.workspace = true
> regex.workspace = true
> serde.workspace = 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<Fingerprint> for [u8; 32] {
> + #[inline]
> + fn from(fp: Fingerprint) -> Self {
> + fp.0
> + }
> +}
> +
> +impl TryFrom<&[u8]> for Fingerprint {
> + type Error = std::array::TryFromSliceError;
> +
> + fn try_from(slice: &[u8]) -> Result<Self, Self::Error> {
> + 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 = [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 = Error;
> +
> + fn from_str(s: &str) -> Result<Self, Error> {
> + let s = s.replace(':', "");
> + let mut fp = [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;
>
> pub mod firewall;
>
> +mod fingerprint;
> +pub use fingerprint::Fingerprint;
> +
> pub mod remotes;
>
> pub mod remote_updates;
> --
> 2.47.3
>
>
>
>
>
>
next prev parent reply other threads:[~2026-08-06 15:23 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-05 13:18 [PATCH cluster/common/datacenter-manager/manager/proxmox v2 00/16] TLS Certificate Staging Shannon Sterz
2026-08-05 13:18 ` [PATCH cluster v2 01/16] setup: allow caller to provide the certificate filename Shannon Sterz
2026-08-05 13:18 ` [PATCH pve-common v2 02/16] certificate: add helper to verify that a certificate was signed by a ca Shannon Sterz
2026-08-06 15:02 ` Fabian Grünbichler
2026-08-05 13:18 ` [PATCH manager v2 03/16] bin/api: add a new staged certificate when renewing self-signed cert Shannon Sterz
2026-08-06 15:39 ` Fabian Grünbichler
2026-08-05 13:18 ` [PATCH manager v2 04/16] api: certificates: if node parameter is 'localhost' return local certs Shannon Sterz
2026-08-05 13:18 ` [PATCH proxmox v2 05/16] pve-api-types: expose certificates info endpoint Shannon Sterz
2026-08-05 13:18 ` [PATCH datacenter-manager v2 06/16] client: allow users to update a changed fingerprint interactively Shannon Sterz
2026-08-05 13:18 ` [PATCH datacenter-manager v2 07/16] cli/api-types: move Fingerprint to common api type crate Shannon Sterz
2026-08-06 15:23 ` Fabian Grünbichler [this message]
2026-08-05 13:18 ` [PATCH datacenter-manager v2 08/16] server: connection: report mismatching fingerprint as untrusted on probe Shannon Sterz
2026-08-05 13:18 ` [PATCH datacenter-manager v2 09/16] ui: wizard: add context if a provided fingerprint did not match remote Shannon Sterz
2026-08-05 13:18 ` [PATCH datacenter-manager v2 10/16] ui: wizard: nodes page: always update fingerprints on user confirmation Shannon Sterz
2026-08-05 13:18 ` [PATCH datacenter-manager v2 11/16] pdm-api-types: implement ApiType for Fingerprint Shannon Sterz
2026-08-05 13:18 ` [PATCH datacenter-manager v2 12/16] pdm-api-types: add staged_fingerprints field to NodeUrl Shannon Sterz
2026-08-05 13:18 ` [PATCH datacenter-manager v2 13/16] server: remotes: lock remotes config when updating it Shannon Sterz
2026-08-05 13:18 ` [PATCH datacenter-manager v2 14/16] server: connection: rotate in staged fingerprints when encountering them Shannon Sterz
2026-08-05 13:18 ` [PATCH datacenter-manager v2 15/16] server: api: tasks: move `spawn_aborted_on_shutdown()` to super module Shannon Sterz
2026-08-05 13:18 ` [PATCH datacenter-manager v2 16/16] server: bin: api: tasks: add task to discover new staged certificates Shannon Sterz
2026-08-06 15:23 ` partially-applied [PATCH cluster/common/datacenter-manager/manager/proxmox v2 00/16] TLS Certificate Staging Fabian Grünbichler
2026-08-06 15:41 ` Fabian Grünbichler
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1786029069.14qi906cuy.astroid@yuna.none \
--to=f.gruenbichler@proxmox.com \
--cc=pdm-devel@lists.proxmox.com \
--cc=s.sterz@proxmox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox