Module tls

Module tls 

Source
Expand description

TLS machinery for listeners (DW-007, feature analysis 4.10 / 4.13).

Responsibilities:

  • process-global crypto provider installation (aws-lc-rs; must happen before the first rustls object is created),
  • building a hot-reloadable rustls::ServerConfig from a ListenerTls terminate block, with SNI-based certificate selection (the single cert_file/key_file pair is the fallback certificate, certificates entries are matched by SNI),
  • outbound TRUST for https dials (#121): the default webpki public root set, PEM-bundle root stores for the trusted_ca_file config field (private CAs), and the shared HTTP/1.1 client-config shape used by upstream connectors, active health probes, and the JWKS fetcher,
  • a minimal TLS ClientHello SNI parser used by passthrough routing, and the passthrough byte-splice itself.

Hot reload model: TlsTermination keeps the current Arc<rustls::ServerConfig> behind an ArcSwap. Each accepted connection clones the current Arc into a fresh TlsAcceptor, so a swap only affects handshakes that start after it: in-flight TLS sessions keep their negotiated configuration and existing connections are never dropped by a reload.

Documented v1 limitation: TLS 1.3 and 1.2 are both enabled with rustls’s default (modern) cipher-suite policy; no cipher/version overrides are configurable yet.

Structs§

SniCertResolver
SNI-aware certificate resolver: exact server-name match against the certificates entries; falls back to the single pair (or the first entry when no pair is configured). Names are compared lowercase per the SNI specification.
TlsTermination
A hot-reloadable TLS termination configuration for one listener.

Enums§

PassthroughAction
Passthrough routing outcome.
SpiffeMtlsConfig
A SPIFFE-aware mTLS rustls config: either a client config (for outbound upstream connections) or a server config (for inbound listener connections). Built from an X.509 SVID and a trust bundle by build_spiffe_mtls_config.
SpiffeMtlsRole
The mTLS role the SPIFFE-aware TLS config plays for a connection. Inbound sidecar connections act as the mTLS server (terminate the peer’s SVID); outbound sidecar connections act as the mTLS client (present the local workload’s SVID).
TlsError
Error loading or building TLS material.

Functions§

admin_mtls_server_config
Build the mTLS-ONLY rustls::ServerConfig for the admin listener (DW-022, decision 6). Client certificates are REQUIRED and must chain to the CA in client_ca_file (WebPkiClientVerifier over a root store loaded from that PEM); the server presents the single cert/key pair. The key is checked against the leaf exactly like dataplane termination, so a torn pair cannot boot. ALPN advertises HTTP/1.1 only — the admin API is a small request/response surface.
build_spiffe_mtls_config
Build a SPIFFE-aware mTLS rustls config from an X.509 SVID and a trust bundle. This is the integration point between the mesh domain (which fetches SVIDs from the SPIRE Workload API) and the TLS machinery here.
extract_spiffe_id_from_peer_cert
Extract the SPIFFE ID (the URI SAN) from a verified peer certificate. This is the auth identity the mesh uses for policy decisions: the sidecar terminates mTLS, verifies the peer SVID against the trust bundle, then extracts the SPIFFE ID from the peer cert’s URI SAN and hands it to the auth layer as the principal/consumer.
fingerprint_colon_hex
Format the SHA-256 fingerprint of a certificate DER as lowercase colon-separated hex (DW-035): the format the mtls_consumer_mapping.consumers[].fingerprint config field and the X-Client-Cert-Fingerprint forwarding header use. The raw hex (no colons) is the credential SELECTOR the authn registry indexes; this colon-separated form is the OPERATOR-facing display format (config and headers), so the two never collide.
handle_passthrough
Peek the ClientHello off a passthrough connection, decide the route, and either splice both directions to the upstream or close.
https_h1_client_config
HTTP/1.1-ALPN rustls client config over the given trust roots: the shared shape for every outbound https dial that speaks HTTP/1.1 — https-protocol upstream connectors, active health probes, and the JWKS fetcher (#121). Keeping one constructor here means a config generation applies IDENTICAL trust and handshake policy across the pooled client, the probes, and the fetcher; http2 upstreams build their own config (same roots, h2 ALPN).
https_h1_client_config_pq
DW-105: HTTP/1.1-ALPN rustls client config with post-quantum hybrid key exchange opt-in. When pq is true, the config is built with a provider that has the X25519+ML-KEM hybrid kx group prepended. The classical X25519 group remains as a fallback for non-PQ servers. When pq is false, this is identical to https_h1_client_config.
https_h1_client_config_with_auth
SEC-03: HTTP/1.1-ALPN rustls client config WITH client auth (mTLS to the upstream). Loads the client cert chain and private key from PEM files and installs them via with_client_auth_cert. Used when an upstream configures mtls.client_cert_file + mtls.client_key_file. Fails with TlsError::Io when the files cannot be read or parsed.
https_h2_client_config_with_auth
SEC-03: HTTP/2-ALPN rustls client config WITH client auth (mTLS to the upstream). Same as https_h1_client_config_with_auth but with h2 ALPN and a client locked to HTTP/2.
https_h3_client_config
HTTP/3-ALPN rustls client config over the given trust roots (DW-108): the shared shape for every outbound H3/QUIC dial — the H3 upstream connector and the QUIC active health probe. QUIC mandates TLS 1.3, so this always negotiates h3 over the same root store the pooled https connector would use (#121: webpki by default, the upstream’s trusted_ca_file bundle when configured). Keeping the constructor here means one trust/handshake policy across the pooled H3 client and its probes, mirroring https_h1_client_config.
install_aws_lc_rs_provider
Install the aws-lc-rs crypto provider as the process-global rustls default. Idempotent: installing twice (e.g. binary + tests in one process) returns Ok the first time and an ignorable error afterwards.
issuer_cn_of_leaf
Extract the issuer CommonName of a leaf certificate (DW-035): the value of the FIRST CN attribute (OID 2.5.4.3) in the issuer RDN sequence. Same strict UTF-8 decode as subject_cn_of_leaf; None when the issuer carries no decodable CN. THE CERTIFICATE IS ALREADY VERIFIED at the TLS layer when this runs; extraction only reads the value for the X-Client-Cert-Issuer-CN forwarding header.
not_after_unix_secs
Extract the notAfter timestamp of a leaf certificate (DW-035) as Unix epoch seconds. The validity SEQUENCE holds two time values: notBefore then notAfter, each a UTCTime (tag 0x17, YYMMDDHHMMSSZ) or GeneralizedTime (tag 0x18, YYYYMMDDHHMMSSZ). Returns None on any structural shortcoming or an unparseable time. THE CERTIFICATE IS ALREADY VERIFIED at the TLS layer when this runs; extraction only reads the value for the X-Client-Cert-Not-After forwarding header.
peek_client_hello_sni
Peek the TLS ClientHello SNI off a TCP stream WITHOUT splicing.
resolve_passthrough
Resolve a passthrough SNI route against the gateway config.
root_store_from_pem_file
Build a rustls RootCertStore from a PEM file of CA certificates (#121). The file may carry SEVERAL certificates — a typical CA bundle lists an anchor plus intermediates — and every certificate in it becomes a trust anchor. Fails with TlsError::Io when the file cannot be read or parsed, and with TlsError::EmptyPem when it parses to zero certificates (an empty trust set is always a configuration mistake, never a valid “trust nothing” — that would silently fail every TLS handshake).
sni_from_client_hello
Parse the SNI server name out of a TLS ClientHello, reassembling handshake fragments across records when the hello does not fit in one (#120).
spki_of_leaf
Extract the DER-encoded SubjectPublicKeyInfo of a leaf certificate by walking Certificate -> TBSCertificate -> (version?) serial, signature, issuer, validity, subject, SPKI. Returns the SPKI DER including its own SEQUENCE header (the same encoding SigningKey::public_key yields) or None on any structural shortcoming (treated as a mismatch by the caller, which rejects).
subject_cn_of_leaf
Extract the subject CommonName of a leaf certificate (#124): the value of the FIRST CN attribute (OID 2.5.4.3) in the subject RDN sequence, decoded from UTF8String / PrintableString / IA5String (the string types CNs carry in practice). The decode is STRICT UTF-8: invalid CN bytes yield None rather than being lossy-folded to U+FFFD, which could collide two distinct malformed names into one selector. None also when the subject carries no CN at all — either way such a certificate can only match a by-fingerprint mTLS credential (the caller falls back to the fingerprint selector). Hand-rolled DER walk (no X.509 parser dependency), same substrate as the private SPKI extractor in this module. THE CERTIFICATE IS ALREADY VERIFIED at the TLS layer when this runs; extraction only reads the match value.
system_root_store
REL-08 (#219): the OS-native root CA store as a rustls RootCertStore. Loaded via rustls-native-certs, which reads the platform trust store (macOS keychain, Linux CA bundle, Windows root store). Used by upstreams that opt into use_system_roots instead of the bundled webpki set. Failures to load native certs fall back to the webpki set rather than failing every TLS handshake, because a missing OS trust store is a deployment mistake, not a security decision — and the operator’s intent (“trust the OS”) is best approximated by “trust what we have” rather than “trust nothing”.
webpki_root_store
The Mozilla (webpki) public root set as a rustls RootCertStore: the DEFAULT trust for every outbound https dial — upstream connectors, active health probes, and the JWKS fetcher (#121 made the per-entity override configurable; this remains what an entity without a trusted_ca_file verifies against). Lives here, next to the other root-store machinery, so all outbound callers share one definition instead of each rebuilding it inline.

Type Aliases§

EndpointPicker
Endpoint resolver for passthrough routing: maps an upstream NAME to a load-balanced (address, port). The dataplane caller builds it from the CURRENT registry (see dwara-bin’s listener), so passthrough picks follow config reloads; Send + Sync because the passthrough path runs on spawned tasks. None means “no dataplane” — the first configured endpoint is used.