tonic/transport/channel/
tls.rs

1use super::service::TlsConnector;
2use crate::transport::{
3    tls::{Certificate, Identity},
4    Error,
5};
6use http::Uri;
7use std::time::Duration;
8use tokio_rustls::rustls::pki_types::TrustAnchor;
9
10/// Configures TLS settings for endpoints.
11#[derive(Debug, Clone, Default)]
12pub struct ClientTlsConfig {
13    domain: Option<String>,
14    certs: Vec<Certificate>,
15    trust_anchors: Vec<TrustAnchor<'static>>,
16    identity: Option<Identity>,
17    assume_http2: bool,
18    #[cfg(feature = "tls-native-roots")]
19    with_native_roots: bool,
20    #[cfg(feature = "tls-webpki-roots")]
21    with_webpki_roots: bool,
22    use_key_log: bool,
23    timeout: Option<Duration>,
24}
25
26impl ClientTlsConfig {
27    /// Creates a new `ClientTlsConfig` using Rustls.
28    pub fn new() -> Self {
29        Self::default()
30    }
31
32    /// Sets the domain name against which to verify the server's TLS certificate.
33    pub fn domain_name(self, domain_name: impl Into<String>) -> Self {
34        ClientTlsConfig {
35            domain: Some(domain_name.into()),
36            ..self
37        }
38    }
39
40    /// Adds the CA Certificate against which to verify the server's TLS certificate.
41    pub fn ca_certificate(self, ca_certificate: Certificate) -> Self {
42        let mut certs = self.certs;
43        certs.push(ca_certificate);
44        ClientTlsConfig { certs, ..self }
45    }
46
47    /// Adds the multiple CA Certificates against which to verify the server's TLS certificate.
48    pub fn ca_certificates(self, ca_certificates: impl IntoIterator<Item = Certificate>) -> Self {
49        let mut certs = self.certs;
50        certs.extend(ca_certificates);
51        ClientTlsConfig { certs, ..self }
52    }
53
54    /// Adds the trust anchor which to verify the server's TLS certificate.
55    pub fn trust_anchor(self, trust_anchor: TrustAnchor<'static>) -> Self {
56        let mut trust_anchors = self.trust_anchors;
57        trust_anchors.push(trust_anchor);
58        ClientTlsConfig {
59            trust_anchors,
60            ..self
61        }
62    }
63
64    /// Adds the multiple trust anchors which to verify the server's TLS certificate.
65    pub fn trust_anchors(
66        mut self,
67        trust_anchors: impl IntoIterator<Item = TrustAnchor<'static>>,
68    ) -> Self {
69        self.trust_anchors.extend(trust_anchors);
70        self
71    }
72
73    /// Sets the client identity to present to the server.
74    pub fn identity(self, identity: Identity) -> Self {
75        ClientTlsConfig {
76            identity: Some(identity),
77            ..self
78        }
79    }
80
81    /// If true, the connector should assume that the server supports HTTP/2,
82    /// even if it doesn't provide protocol negotiation via ALPN.
83    pub fn assume_http2(self, assume_http2: bool) -> Self {
84        ClientTlsConfig {
85            assume_http2,
86            ..self
87        }
88    }
89
90    /// Use key log as specified by the `SSLKEYLOGFILE` environment variable.
91    pub fn use_key_log(self) -> Self {
92        ClientTlsConfig {
93            use_key_log: true,
94            ..self
95        }
96    }
97
98    /// Enables the platform's trusted certs.
99    #[cfg(feature = "tls-native-roots")]
100    pub fn with_native_roots(self) -> Self {
101        ClientTlsConfig {
102            with_native_roots: true,
103            ..self
104        }
105    }
106
107    /// Enables the webpki roots.
108    #[cfg(feature = "tls-webpki-roots")]
109    pub fn with_webpki_roots(self) -> Self {
110        ClientTlsConfig {
111            with_webpki_roots: true,
112            ..self
113        }
114    }
115
116    /// Activates all TLS roots enabled through `tls-*-roots` feature flags
117    pub fn with_enabled_roots(self) -> Self {
118        let config = self;
119
120        #[cfg(feature = "tls-native-roots")]
121        let config = config.with_native_roots();
122        #[cfg(feature = "tls-webpki-roots")]
123        let config = config.with_webpki_roots();
124
125        config
126    }
127
128    /// Sets the timeout for the TLS handshake.
129    pub fn timeout(self, timeout: Duration) -> Self {
130        ClientTlsConfig {
131            timeout: Some(timeout),
132            ..self
133        }
134    }
135
136    pub(crate) fn into_tls_connector(self, uri: &Uri) -> Result<TlsConnector, crate::BoxError> {
137        let domain = match &self.domain {
138            Some(domain) => domain,
139            None => uri.host().ok_or_else(Error::new_invalid_uri)?,
140        };
141        TlsConnector::new(
142            self.certs,
143            self.trust_anchors,
144            self.identity,
145            domain,
146            self.assume_http2,
147            self.use_key_log,
148            self.timeout,
149            #[cfg(feature = "tls-native-roots")]
150            self.with_native_roots,
151            #[cfg(feature = "tls-webpki-roots")]
152            self.with_webpki_roots,
153        )
154    }
155}