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
impl ClusterCa
Sourcepub fn generate() -> Self
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.
Sourcepub async fn load_or_generate(path: &Path) -> Result<Self, SecretsError>
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::Storagefor any IO error reading or writing the file, or if an existing file has the wrong length.
Sourcepub fn ca_public_key_b64(&self) -> String
pub fn ca_public_key_b64(&self) -> String
CA verifying key as URL-safe no-pad base64.
Sourcepub fn ca_kid(&self) -> String
pub fn ca_kid(&self) -> String
Short CA key id: first 8 hex chars of SHA-256(CA verifying key bytes).
Sourcepub fn verifying_key(&self) -> VerifyingKey
pub fn verifying_key(&self) -> VerifyingKey
CA verifying key for verification (not exported through trait).
Sourcepub fn issue_ca_cert(
&self,
active_kid: String,
active_pubkey_b64: String,
cluster_domain: String,
grace: Duration,
) -> Result<CaCert, SecretsError>
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::Providerif serializing the canonical body fails (should not happen with the well-formedCaCertstruct).
Sourcepub fn verify_ca_cert(
ca_pubkey_b64: &str,
cert: &CaCert,
) -> Result<(), SecretsError>
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:
- Decodes the
sig_by_cabase64. - Recomputes the canonical body bytes (
sig_by_cacleared). - Calls
verify_stricton the CA pubkey. - Checks
expires_at > nowso 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
SecretsError::Providerfor any decode/verification/expiry failure with an actionable message.
Trait Implementations§
Auto Trait Implementations§
impl Freeze for ClusterCa
impl RefUnwindSafe for ClusterCa
impl Send for ClusterCa
impl Sync for ClusterCa
impl Unpin for ClusterCa
impl UnsafeUnpin for ClusterCa
impl UnwindSafe for ClusterCa
Blanket Implementations§
Source§impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
Source§impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
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