//! Shared TLS configuration for pom's outbound HTTP. //! //! Every probe (health, CORS, routes, peer, alerts) trusts the bundled Mozilla //! root set via `webpki-roots`, the same anchor the TLS-expiry check reports //! against, so a host with an extra local root cannot make the HTTP check and //! the certificate check disagree about one target. The rustls provider is ring //! (pure Rust), installed process-wide by [`install_crypto_provider`] at startup. /// Install ring as the process-wide rustls crypto provider. Idempotent (guarded /// by a `Once`); safe to call from `main` at startup and from every config /// builder, so a TLS client can never be built before a provider is installed. pub fn install_crypto_provider() { static INSTALLED: std::sync::Once = std::sync::Once::new(); INSTALLED.call_once(|| { let _ = rustls::crypto::ring::default_provider().install_default(); }); } /// A rustls client config pinned to the bundled webpki (Mozilla) roots. pub fn webpki_client_config() -> rustls::ClientConfig { // `ClientConfig::builder()` reads the process-default provider, so make sure // ring is installed even if this runs before `main`'s explicit install (tests). install_crypto_provider(); let mut roots = rustls::RootCertStore::empty(); roots.extend(webpki_roots::TLS_SERVER_ROOTS.iter().cloned()); rustls::ClientConfig::builder() .with_root_certificates(roots) .with_no_client_auth() } /// A `reqwest` client builder that trusts the webpki root set. Callers add their /// own timeout / redirect policy, then `.build()`. reqwest is compiled /// `rustls-no-provider`, so without this preconfigured config it would fall back /// to the OS platform verifier, a different trust model than the cert check uses. pub fn https_client_builder() -> reqwest::ClientBuilder { reqwest::Client::builder().use_preconfigured_tls(webpki_client_config()) }