Skip to main content

Crate solti_tls

Crate solti_tls 

Source
Expand description

§solti-tls

Shared TLS / mTLS configuration for Solti network-facing crates.

Builders hold intent, a PemSource - filesystem path or in-memory PEM bytes for each cert/key. Defer all I/O and parsing to ServerTlsConfig::into_rustls_config / ClientTlsConfig::into_rustls_config, which produce a ready rustls::ServerConfig / rustls::ClientConfig.

§Architecture

  ┌──────────────────────┐        ┌──────────────────────┐
  │  PemSource::Path     │        │  PemSource::Bytes    │   intent: where PEM lives
  │  (read at I/O time)  │        │  (in-memory buffer)  │
  └──────────┬───────────┘        └──────────┬───────────┘
             └───────────────┬───────────────┘
                             ▼
        ┌───────────────────────────────────────────────┐
        │  ServerTlsConfig / ClientTlsConfig            │   built via *Builder
        │   cert · key · client_ca/ca · alpn            │   (pure, cloneable intent)
        └───────────────────────┬───────────────────────┘
                                │ into_rustls_config()
                                │   1. ensure_default_provider()  (install ring once)
                                │   2. PemSource::read()          (I/O happens here)
                                │   3. load_certs_from_pem / load_key_from_pem
                                │   4. RootCertStore + (mTLS) WebPki*Verifier
                                │   5. apply ALPN
                                ▼
        ┌───────────────────────────────────────────────┐
        │  rustls::ServerConfig / rustls::ClientConfig  │
        └───────────────────────────────────────────────┘

No I/O, provider install, or parsing happens until into_rustls_config() is called; the builders are pure intent.

§Features

AreaDescriptionKey types
PEM sourcesPath-on-disk or in-memory bytes; read lazily at config-build time.PemSource
Server TLSServer cert/key, optional client-CA (mTLS), ALPN.ServerTlsConfig, ServerTlsConfigBuilder
Client TLSTrust roots (CA), optional client cert/key (mTLS), ALPN.ClientTlsConfig, ClientTlsConfigBuilder
ParsingPure PEM→DER helpers for certs and the first private key.load_certs_from_pem, load_key_from_pem
ProviderIdempotent process-wide installation of the ring crypto provider.ensure_default_provider
ErrorsOne #[non_exhaustive] enum across I/O, parse, and rustls.TlsError

§Security model

What IS verified

  • Server chain: a client built from ClientTlsConfig verifies the server’s certificate chains to the CA bundle you pass to ca(..) (rustlsWebPkiServerVerifier). Trust roots come only from your PEM - there is no OS / rustls-native-certs trust integration.
  • Client chain (mTLS): when require_client_ca(..) is set, the server demands and verifies a client cert chaining to that CA. Client auth is then mandatory: connections without a valid client cert are rejected at the handshake.

What is NOT verified here (the caller’s responsibility)

  • Hostname / SAN: into_rustls_config() does not check the server hostname. SAN/identity matching happens when you call TlsConnector::connect(server_name, ..): you must pass the correct ServerName. A wrong or placeholder name silently disables identity checking even though the chain still validates.
  • Revocation: no OCSP / CRL / stapling; a revoked-but-unexpired cert is accepted. Short cert lifetimes are the intended mitigation.
  • TLS versions & suites: rustls safe defaults only (the workspace enables TLS 1.2 + 1.3); no explicit minimum-version or cipher policy.
  • Crypto provider: ring is installed via ensure_default_provider; aws-lc-rs is not selectable (install your own provider first if needed).

§Example

use solti_tls::ServerTlsConfig;

// Use real PEM files in production; placeholder bytes keep this hermetic.
let cfg = ServerTlsConfig::builder()
    .cert_pem_bytes(b"-----BEGIN CERTIFICATE-----\n...".to_vec())
    .key_pem_bytes(b"-----BEGIN PRIVATE KEY-----\n...".to_vec())
    .with_alpn(["h2"])              // gRPC; ["h2", "http/1.1"] for HTTP
    .build()?;                      // validates required fields, no I/O yet

assert_eq!(cfg.alpn, vec![b"h2".to_vec()]);
// cfg.into_rustls_config()? would now read + parse the PEM into a
// rustls::ServerConfig (requires real cert/key material).

§Also

Structs§

ClientTlsConfig
Client-side TLS configuration.
ClientTlsConfigBuilder
Incremental builder for ClientTlsConfig.
ServerTlsConfig
Server-side TLS configuration.
ServerTlsConfigBuilder
Incremental builder for ServerTlsConfig.

Enums§

PemSource
Where a PEM blob lives.
TlsError

Functions§

ensure_default_provider
Install the ring crypto provider as the process-wide default if none is set.
load_certs_from_pem
Parse all CERTIFICATE blocks out of a PEM byte stream, in file order (leaf-first by convention for a chain).
load_key_from_pem
Parse the first private key (PKCS#8, PKCS#1, or SEC1) out of a PEM byte stream.