Skip to main content

CertManager

Struct CertManager 

Source
pub struct CertManager {
    pub policy: Policy,
    pub issuers: Vec<Arc<dyn CertIssuer>>,
    pub certificates: Arc<dyn CertStore>,
    pub storage: Arc<dyn Storage>,
    pub cache: Arc<CertCache>,
    pub on_demand: Option<Arc<OnDemandConfig>>,
    pub on_event: Option<Arc<dyn Fn(&str, &Value) -> Result<()> + Send + Sync>>,
    pub subject_transformer: Option<Arc<dyn Fn(&str) -> Result<String> + Send + Sync>>,
    pub cert_selection: Option<Arc<dyn CertificateSelector>>,
    /* private fields */
}
Expand description

Central configuration for automatic TLS certificate management.

CertManager coordinates the full certificate lifecycle: obtainment, renewal, revocation, OCSP stapling, caching, and storage. It holds references to one or more CertIssuer implementations, a persistent Storage backend, and a shared in-memory CertCache.

Use CertManager::builder() to construct an instance with sensible defaults.

Fields§

§policy: Policy

What should happen. Plain data, so it can be built, cloned, compared and printed on its own.

§issuers: Vec<Arc<dyn CertIssuer>>

Certificate issuers, tried in order until one succeeds.

Defaults to a single AcmeIssuer configured for Let’s Encrypt production.

§certificates: Arc<dyn CertStore>

Where certificates go.

Defaults to a KeyValueCertStore over storage, so a deployment that has said nothing keeps exactly the layout it already has on disk.

§storage: Arc<dyn Storage>

Key-value storage for everything that does not go through CertStore yet: OCSP staples, ACME account data, challenge state, and cluster locks.

§cache: Arc<CertCache>

Shared in-memory certificate cache.

§on_demand: Option<Arc<OnDemandConfig>>

On-demand TLS (optional). When set, certificate operations may be deferred to TLS handshake time for domains that are not yet managed.

§on_event: Option<Arc<dyn Fn(&str, &Value) -> Result<()> + Send + Sync>>

Optional event callback invoked when notable lifecycle events occur.

The callback receives an event name (one of the EVENT_* constants) and a JSON value containing event-specific data. Returning an error from the callback may abort the current operation (for critical events like EVENT_CERT_OBTAINING). Callbacks should return quickly as they are invoked synchronously.

§subject_transformer: Option<Arc<dyn Fn(&str) -> Result<String> + Send + Sync>>

Optional transform applied once per obtain or management operation, before validating, reading storage or taking lifecycle locks. The transformed subject is the managed identifier, normalized to lowercase. A queued job keeps that identity across retries; resubmission resolves it again. Explicit renewal and revocation take managed identifiers directly.

§cert_selection: Option<Arc<dyn CertificateSelector>>

Optional custom certificate selector for TLS handshakes.

Implementations§

Source§

impl CertManager

Source

pub fn policy(&self) -> &Policy

What this manager was told to do.

Source

pub fn builder() -> CertManagerBuilder

Create a new CertManagerBuilder.

Settings start at Policy::default(), which documents what each one is and why it defaults where it does. Everything else — issuers, cache, hooks — starts empty, and a Storage must be given.

Source§

impl CertManager

Source

pub async fn make_certificate_with_ocsp( &self, cert_res: &CertificateResource, ) -> Result<Certificate>

Parse a CertificateResource into a Certificate, applying OCSP stapling if enabled.

The certificate PEM is decoded into a chain of DER-encoded certificates, and the private key PEM is decoded into raw key bytes. If OCSP stapling is not disabled, the function fetches and attaches an OCSP response (using the storage cache when possible).

Source§

impl CertManager

Source

pub async fn manage(&self, domains: &[String]) -> Result<()>

Manage certificates for the given domain names synchronously.

This is the primary entry point for certificate management. For each domain:

  1. Skip currently usable managed entries.
  2. Load storage resources and cache only certificates currently valid.
  3. If not found in storage – obtain a new certificate from the configured issuers.
  4. If loaded from storage, check if renewal is needed and renew if so.

“Synchronously” means that certificate operations are performed in the foreground without background retries. Use CertManager::manage_in_background instead if you want background retry behaviour.

Returns on the first error encountered.

Source

pub async fn manage_in_background(&self, domains: &[String]) -> Result<()>

Manage certificates for the given domain names asynchronously.

Same as manage, but ACME operations (obtain, renew) are submitted as background tasks via the JobQueue. This method returns as soon as each domain’s management task has been submitted – certificates may not yet be ready when this method returns. At most four jobs execute and 68 are admitted per manager family; further submissions apply backpressure until capacity is available. Backoff releases execution. At most 64 jobs retain retry records, leaving four admission records for new work. When retention is full, a failed job ends with cert_failed / error_kind = "retry_backlog_full"; it can be resubmitted later. Success here means submitted, not issued successfully.

Source

pub async fn cache_certificate(&self, domain: &str) -> Result<Certificate>

Load a managed certificate from storage and add it to the in-memory cache. A future or expired certificate returns a validity error without replacing any working certificate already in the cache.

Source

pub async fn load_certificate( &self, domain: &str, ) -> Result<Option<Certificate>>

Load a certificate from storage for the given domain.

Tries all configured issuers, preferring currently valid certificates. Returns the best stored resource even if it needs renewal; this method does not publish it to the serving cache. Returns None when absent.

Source§

impl CertManager

Source

pub async fn obtain(&self, domain: &str) -> Result<()>

Obtain a new certificate synchronously (foreground, no retries).

Generates a new private key and CSR, then tries each configured issuer in order until one succeeds. The resulting certificate, key, and metadata are persisted to storage. A distributed lock is held during the operation to prevent duplicate issuance.

Source

pub async fn obtain_in_background(&self, domain: &str) -> Result<()>

Obtain a new certificate asynchronously (background, with retries).

Same as CertManager::obtain but wraps the operation in do_with_retry, automatically retrying transient failures with exponential backoff.

Source§

impl CertManager

Source

pub async fn renew(&self, domain: &str, force: bool) -> Result<()>

Renew a certificate synchronously (foreground, no retries).

Loads the existing certificate from storage, checks if renewal is needed (unless force is true), generates a new key and CSR, and tries each configured issuer in order. A distributed lock is held during the operation. With force = true, a quarantined stored resource may supply the SANs for a replacement with a new leaf; its old leaf remains blocked and cannot be republished. A stored certificate outside its validity period always needs renewal.

Source

pub async fn renew_in_background(&self, domain: &str, force: bool) -> Result<()>

Renew a certificate asynchronously (background, with retries).

Same as CertManager::renew but wraps the operation in do_with_retry, automatically retrying transient failures with exponential backoff.

Source§

impl CertManager

Source

pub async fn revoke(&self, domain: &str, reason: Option<u8>) -> Result<()>

Revoke the certificate for domain.

Select the stored resource using the same validity/latest-issuance preference as certificate loading, independent of issuer order. Pending or confirmed markers do not lower its rank: recording intent alone cannot redirect a retry to an older backup. This revokes one stored resource, not every certificate that can serve this domain. Use Self::revoke_from_issuer to target a particular issuer’s resource.

Every invocation selects from current storage under the lifecycle lock; if resources or their validity state have changed, a new call may select a different leaf. Before calling the provider, persist revocation intent in the shared Storage and quarantine this leaf in the local cache. Provider errors do not undo that intent. After confirmation, delete the matching stored resource; cleanup retries skip a provider call already recorded as confirmed. reason is an optional RFC 5280 revocation reason code (0-10).

The operation runs in an owned task: dropping the caller’s future does not cancel it. Await the result to observe provider, cleanup and task errors. Runtime/process shutdown can still interrupt it; a persistent pending marker blocks reuse until provider reconciliation and cleanup.

Other instances must share the storage/lock backend and refresh their existing caches with Self::refresh_revocations or maintenance. This does not close existing TLS sessions or invalidate separately cloned signing keys. A provider without crate::Revoker support is an error.

Source

pub async fn revoke_from_issuer( &self, domain: &str, issuer_key: &str, reason: Option<u8>, ) -> Result<()>

Revoke the resource currently stored for domain under an exact configured issuer_key. Other issuers are not consulted or used as fallbacks, including when the selected provider is unavailable or does not support revocation.

Unlike default target selection, this recovery/cleanup path needs only a parseable leaf certificate: an expired certificate, incorrect SAN or damaged private key does not prevent provider-side revocation. Ownership, locking, persisted intent and cleanup semantics are the same as Self::revoke. This selects an issuer, not an immutable historical leaf: if that issuer’s resource was replaced, a new call targets its current resource.

Source

pub async fn refresh_revocations(&self) -> Result<usize>

Poll shared revocation intent and quarantine matching cached leaves. Other processes’ existing caches are not synchronously invalidated; applications may call this after receiving their own invalidation event. Reads at most eight unique leaf markers concurrently and returns the number of quarantined leaves. Alternate chains share one marker read. A failed read does not prevent other leaves from being quarantined; the first snapshot-order error is returned after all reads finish.

Source§

impl CertManager

Source

pub fn server_config(&self) -> ServerConfig

Build a rustls::ServerConfig wired up to serve certificates from this config’s cache.

The returned server config uses a CertResolver backed by the config’s in-memory certificate cache, with ALPN protocols set to ["h2", "http/1.1"].

If default_server_name or fallback_server_name are configured, they are applied to the resolver. On-demand issuance and custom certificate selection are also applied. Without an explicit on-demand obtain callback, this manager performs issuance in the background; the first handshake may still fail.

Source§

impl CertManager

Source

pub async fn client_credentials( &self, domain: &str, ) -> Result<(Vec<CertificateDer<'static>>, PrivateKeyDer<'static>)>

Build TLS client credentials from a managed certificate.

Loads the certificate and private key for domain from the cache (or storage) and returns them as a pair suitable for constructing a rustls::ClientConfig for mutual TLS (mTLS) authentication. Candidates must be time-valid and not locally known to be revoked. Each call reads persisted revocation intent even for a warm cache; backend errors are propagated. An unusable leaf does not hide a usable sibling. Server Must-Staple policy is not applied to client identities, and this method does not query an OCSP responder.

Returned credentials are an immutable validated snapshot. A later revocation or expiry does not invalidate previously exported keys or configurations; construct fresh credentials to check current state.

§Returns

A tuple of (cert_chain, private_key) where:

  • cert_chain is a list of DER-encoded certificates (leaf first).
  • private_key is the DER-encoded private key.
§Errors

Returns an error if no usable certificate is found for domain, or if persisted revocation intent cannot be read.

Source

pub async fn client_config( &self, domain: &str, roots: impl Into<Arc<RootCertStore>>, ) -> Result<ClientConfig>

Build a rustls::ClientConfig for mutual TLS (mTLS) using a managed certificate.

This is a convenience wrapper around Self::client_credentials. roots supplies the trust anchors used to authenticate the server; client credentials do not establish trust in the server’s certificate. Pass a store (or a shared Arc of one) populated with your trusted CAs. An empty store rejects servers whose certificates require a trust anchor.

§Errors

Returns an error if no suitable certificate is found or if TLS configuration fails.

Trait Implementations§

Source§

impl Debug for CertManager

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<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

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> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. 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> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

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 = !

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

fn try_from(value: U) -> Result<T, !>

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