Skip to main content

Crate rustls_native_roots_cache

Crate rustls_native_roots_cache 

Source
Expand description

Process-wide cache for the system trust store.

rustls_native_certs::load_native_certs reaches into the OS keychain (Security framework on macOS, NSS / OpenSSL stores on Linux). On macOS the underlying Sec* APIs are not concurrency-safe under load — multiple threads calling them in parallel can return errSecIO (-36) on what would otherwise succeed. Production daemons that build many distinct rustls ClientConfigs (one per upstream-TLS fingerprint, e.g.) hit this whenever a reload introduces a handful of new fingerprints concurrently.

The fix is a process-wide cache: read the trust store once per process, share the resulting rustls::RootCertStore behind Arc. The std::sync::OnceLock initializer barrier serialises the (single) load attempt; every subsequent caller gets a cheap Arc::clone.

In-process the OnceLock is sufficient. Across processes (e.g. a test runner that boots multiple binaries in parallel) each binary still makes its own first call, and those simultaneous calls can lose to keychain contention. The init path therefore retries on transient failure with a small backoff before giving up — errSecIO is documented by Apple as recoverable, and the happy path skips the backoff entirely.

Failure semantics: after the bounded retries are exhausted the outcome is sticky. The cached error re-yields on every subsequent call so the operator sees consistent behaviour and can restart the process to attempt a fresh load — there is no per-request retry storm against an OS API that is already telling us it is unhappy.

Structs§

NativeRootsError
Shared error type. Carries an operator-readable message; the underlying rustls_native_certs::Error is not Clone, so we stringify at first-failure time and re-yield the same string on subsequent calls.

Functions§

native_roots
Return the cached system trust store, loading it on first call.
warm_native_roots
Eagerly trigger the first load. Useful when a daemon’s boot path wants to know the trust-store status before any TLS code runs — idempotent; subsequent calls return the cached result without re-touching the OS keychain.