tonic/transport/channel/
tls.rs1use super::service::TlsConnector;
2use crate::transport::{
3 Error,
4 tls::{Certificate, Identity},
5};
6use http::Uri;
7use std::sync::Arc;
8use std::time::Duration;
9use tokio_rustls::rustls::client::danger::ServerCertVerifier;
10use tokio_rustls::rustls::pki_types::TrustAnchor;
11
12#[derive(Debug, Clone, Default)]
14pub struct ClientTlsConfig {
15 domain: Option<String>,
16 certs: Vec<Certificate>,
17 trust_anchors: Vec<TrustAnchor<'static>>,
18 identity: Option<Identity>,
19 assume_http2: bool,
20 #[cfg(feature = "tls-native-roots")]
21 with_native_roots: bool,
22 #[cfg(feature = "tls-webpki-roots")]
23 with_webpki_roots: bool,
24 use_key_log: bool,
25 timeout: Option<Duration>,
26}
27
28impl ClientTlsConfig {
29 pub fn new() -> Self {
31 Self::default()
32 }
33
34 pub fn domain_name(self, domain_name: impl Into<String>) -> Self {
36 ClientTlsConfig {
37 domain: Some(domain_name.into()),
38 ..self
39 }
40 }
41
42 pub fn ca_certificate(self, ca_certificate: Certificate) -> Self {
44 let mut certs = self.certs;
45 certs.push(ca_certificate);
46 ClientTlsConfig { certs, ..self }
47 }
48
49 pub fn ca_certificates(self, ca_certificates: impl IntoIterator<Item = Certificate>) -> Self {
51 let mut certs = self.certs;
52 certs.extend(ca_certificates);
53 ClientTlsConfig { certs, ..self }
54 }
55
56 pub fn trust_anchor(self, trust_anchor: TrustAnchor<'static>) -> Self {
58 let mut trust_anchors = self.trust_anchors;
59 trust_anchors.push(trust_anchor);
60 ClientTlsConfig {
61 trust_anchors,
62 ..self
63 }
64 }
65
66 pub fn trust_anchors(
68 mut self,
69 trust_anchors: impl IntoIterator<Item = TrustAnchor<'static>>,
70 ) -> Self {
71 self.trust_anchors.extend(trust_anchors);
72 self
73 }
74
75 pub fn identity(self, identity: Identity) -> Self {
77 ClientTlsConfig {
78 identity: Some(identity),
79 ..self
80 }
81 }
82
83 pub fn assume_http2(self, assume_http2: bool) -> Self {
86 ClientTlsConfig {
87 assume_http2,
88 ..self
89 }
90 }
91
92 pub fn use_key_log(self) -> Self {
94 ClientTlsConfig {
95 use_key_log: true,
96 ..self
97 }
98 }
99
100 #[cfg(feature = "tls-native-roots")]
102 pub fn with_native_roots(self) -> Self {
103 ClientTlsConfig {
104 with_native_roots: true,
105 ..self
106 }
107 }
108
109 #[cfg(feature = "tls-webpki-roots")]
111 pub fn with_webpki_roots(self) -> Self {
112 ClientTlsConfig {
113 with_webpki_roots: true,
114 ..self
115 }
116 }
117
118 pub fn with_enabled_roots(self) -> Self {
120 let config = self;
121
122 #[cfg(feature = "tls-native-roots")]
123 let config = config.with_native_roots();
124 #[cfg(feature = "tls-webpki-roots")]
125 let config = config.with_webpki_roots();
126
127 config
128 }
129
130 pub fn timeout(self, timeout: Duration) -> Self {
132 ClientTlsConfig {
133 timeout: Some(timeout),
134 ..self
135 }
136 }
137
138 pub(crate) fn into_tls_connector(self, uri: &Uri) -> Result<TlsConnector, crate::BoxError> {
139 self.build_tls_connector(uri, None)
140 }
141
142 pub(crate) fn into_tls_connector_with_verifier(
143 self,
144 uri: &Uri,
145 verifier: Arc<dyn ServerCertVerifier>,
146 ) -> Result<TlsConnector, crate::BoxError> {
147 self.build_tls_connector(uri, Some(verifier))
148 }
149
150 fn build_tls_connector(
151 self,
152 uri: &Uri,
153 server_cert_verifier: Option<Arc<dyn ServerCertVerifier>>,
154 ) -> Result<TlsConnector, crate::BoxError> {
155 let domain = match &self.domain {
156 Some(domain) => domain,
157 None => uri.host().ok_or_else(Error::new_invalid_uri)?,
158 };
159 TlsConnector::new(
160 self.certs,
161 self.trust_anchors,
162 self.identity,
163 server_cert_verifier,
164 domain,
165 self.assume_http2,
166 self.use_key_log,
167 self.timeout,
168 #[cfg(feature = "tls-native-roots")]
169 self.with_native_roots,
170 #[cfg(feature = "tls-webpki-roots")]
171 self.with_webpki_roots,
172 )
173 }
174}