pub struct CustomCaTransport { /* private fields */ }Expand description
Custom CA trust root (DER-encoded). No Authorization header is injected.
Use when the server presents a certificate signed by a private CA.
Pair with any AuthProvider for credential injection — including
BearerAuth or BasicAuth if the server also requires credentials.
§Trust scope (bd:JMAP-6r7c.57)
The bundled public webpki-roots are DISABLED in the constructed reqwest client. This type is intended for private-CA pinning — connecting to a JMAP server identified by a private CA the operator controls, refusing certificates signed by any public CA. That is the threat model where this transport matters: a corporate internal JMAP server, a service-mesh deployment, an air-gapped network. A compromised or malicious public CA (DigiNotar 2011, Symantec 2017, etc.) issuing a certificate for the target host name would otherwise bypass the private-CA defense entirely; disabling the public roots closes that gap.
If you want trust against BOTH the bundled public roots AND a custom
CA (a “hybrid” deployment), CustomCaTransport is the wrong tool —
implement TransportConfig directly with the additive behaviour
(reqwest::ClientBuilder::add_root_certificate does NOT call
.tls_built_in_root_certs(false) by default, so a hand-rolled impl
has the additive shape automatically).
Implementations§
Source§impl CustomCaTransport
impl CustomCaTransport
Sourcepub fn new(der_cert: Vec<u8>) -> Self
pub fn new(der_cert: Vec<u8>) -> Self
Construct a CustomCaTransport from a DER-encoded CA certificate.
Sourcepub fn from_pem_bytes(pem_bytes: &[u8]) -> Result<Self, ClientError>
pub fn from_pem_bytes(pem_bytes: &[u8]) -> Result<Self, ClientError>
Construct a CustomCaTransport from a PEM-encoded CA certificate
(bd:JMAP-6r7c.37).
Operators typically distribute private-CA certificates as PEM
files (text-format, -----BEGIN CERTIFICATE----- framing).
Without this helper, every caller has to convert PEM to DER
themselves before passing to CustomCaTransport::new:
// Without from_pem_bytes (the long way):
let pem_bytes = std::fs::read("ca.pem")?;
let der = rustls_pemfile::certs(&mut pem_bytes.as_slice())
.next()
.transpose()?
.ok_or("no certificate in PEM file")?
.to_vec();
let transport = CustomCaTransport::new(der);
// With from_pem_bytes (the short way):
let transport = CustomCaTransport::from_pem_bytes(&std::fs::read("ca.pem")?)?;The first PEM-framed certificate in pem_bytes is used. To use
a different certificate from a multi-cert bundle, split the
bundle yourself and pass the desired one. Multi-cert chains
(root + intermediate) require constructing a custom
TransportConfig implementation that adds multiple roots —
CustomCaTransport is single-root.
§Errors
Returns ClientError::InvalidArgument if pem_bytes does not
contain a recognisable PEM-framed certificate or if the PEM
body cannot be base64-decoded.
DER validity is NOT checked at this stage. This matches the
existing CustomCaTransport::new contract — invalid DER
(PEM body that decodes to non-DER bytes) is detected later when
the JmapClient is constructed and the underlying transport
tries to load the root, at which point it surfaces as
ClientError::Http. The PEM helper deliberately matches the
DER helper’s behaviour: cheap validation here, full validation
at client-build time.
Trait Implementations§
Source§impl Clone for CustomCaTransport
impl Clone for CustomCaTransport
Source§fn clone(&self) -> CustomCaTransport
fn clone(&self) -> CustomCaTransport
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for CustomCaTransport
Manual Debug impl that redacts the DER-encoded CA bytes
(bd:JMAP-6r7c.13).
impl Debug for CustomCaTransport
Manual Debug impl that redacts the DER-encoded CA bytes
(bd:JMAP-6r7c.13).
The DER bytes are not a credential, but they are deployment-identifying
material: a CA certificate uniquely identifies the deployment’s PKI
(Subject DN, public key, signing algorithm, validity window, X.509
extensions). In federated or multi-tenant scenarios, surfacing those
bytes in tracing output reveals which private-CA-using customer the
client is configured to talk to. Print the length only and let the
caller obtain the bytes via a constructor-controlled path if they
genuinely need them.
Mirrors the redacting Debug impls on BearerAuth and BasicAuth
in this file and on Session and AccountInfo in request.rs.
Source§impl TransportConfig for CustomCaTransport
impl TransportConfig for CustomCaTransport
Source§fn build_client(&self) -> Result<HttpClient, ClientError>
fn build_client(&self) -> Result<HttpClient, ClientError>
HttpClient for this transport configuration.