Skip to main content

ClusterCa

Struct ClusterCa 

Source
pub struct ClusterCa { /* private fields */ }
Expand description

Long-lived cluster CA keypair.

Identifies this cluster across the entire federation. NEVER rotated — rotation would invalidate every CaCert this cluster has ever issued and break federation trust. Stored as a raw 32-byte Ed25519 seed at {data_dir}/cluster_ca.key (0600).

The per-rotation signing keys (see ClusterSigner) live in a separate JSON keystore at cluster_signing.key. The CA key is deliberately not part of that keystore so it survives the rotation-and-prune machinery.

Implementations§

Source§

impl ClusterCa

Source

pub fn generate() -> Self

Generate a fresh CA keypair using the OS CSPRNG.

§Panics

Panics if the OS CSPRNG fails — same fail-loud behavior as ClusterSigner::generate.

Source

pub async fn load_or_generate(path: &Path) -> Result<Self, SecretsError>

Load the CA seed from path, or generate + persist a fresh one if the file does not exist.

On creation the file is written atomically (tmp + rename) with mode 0600 on Unix. The 32-byte seed is the entirety of the file — no JSON, no headers; this is intentionally a simpler format than the signing keystore because the CA key never rotates.

§Errors
  • SecretsError::Storage for any IO error reading or writing the file, or if an existing file has the wrong length.
Source

pub fn ca_public_key_b64(&self) -> String

CA verifying key as URL-safe no-pad base64.

Source

pub fn ca_kid(&self) -> String

Short CA key id: first 8 hex chars of SHA-256(CA verifying key bytes).

Source

pub fn verifying_key(&self) -> VerifyingKey

CA verifying key for verification (not exported through trait).

Source

pub fn issue_ca_cert( &self, active_kid: String, active_pubkey_b64: String, cluster_domain: String, grace: Duration, ) -> Result<CaCert, SecretsError>

Build a [CaCert] binding active_kid (whose verifying-key base64 is active_pubkey_b64) to cluster_domain for the window [now, now + grace]. The result’s sig_by_ca is the CA’s Ed25519 signature over the canonical bytes of the body.

“Canonical bytes” = serde_json::to_vec of a CaCert with the signature field cleared (""). Verifiers must do the same transformation before calling verify_strict.

§Errors
  • SecretsError::Provider if serializing the canonical body fails (should not happen with the well-formed CaCert struct).
Source

pub fn verify_ca_cert( ca_pubkey_b64: &str, cert: &CaCert, ) -> Result<(), SecretsError>

Verify a CaCert against a CA public key.

The CA public key is the bytes that an importer obtained out-of-band from a [crate::TrustBundle]. Verification:

  1. Decodes the sig_by_ca base64.
  2. Recomputes the canonical body bytes (sig_by_ca cleared).
  3. Calls verify_strict on the CA pubkey.
  4. Checks expires_at > now so an expired cert is rejected.

Does NOT check cluster_domain — that’s the caller’s job (typically: “does the cert’s cluster_domain match the TrustBundle we looked up by domain?”).

§Errors

Trait Implementations§

Source§

impl Debug for ClusterCa

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<'a, T, E> AsTaggedExplicit<'a, E> for T
where T: 'a,

Source§

fn explicit(self, class: Class, tag: u32) -> TaggedParser<'a, Explicit, Self, E>

Source§

impl<'a, T, E> AsTaggedImplicit<'a, E> for T
where T: 'a,

Source§

fn implicit( self, class: Class, constructed: bool, tag: u32, ) -> TaggedParser<'a, Implicit, Self, E>

Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more