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