1use std::{path::Path, sync::Arc};
5
6use rustls::{
7 ClientConfig as RustlsClientConfig, DigitallySignedStruct, Error, RootCertStore,
8 SignatureScheme,
9 client::danger::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier},
10 version::{TLS12, TLS13},
11};
12use rustls_pki_types::pem::PemObject;
13use rustls_pki_types::{CertificateDer, PrivateKeyDer, ServerName, UnixTime};
14use serde;
15use serde::Deserialize;
16use tracing::warn;
17
18use super::common::{Config, ConfigError, RustlsConfigLoader};
19use crate::component::configuration::{Configuration, ConfigurationError};
20
21#[derive(Debug, Deserialize, PartialEq, Clone)]
22pub struct TlsClientConfig {
23 #[serde(flatten, default)]
25 pub config: Config,
26
27 #[serde(default = "default_insecure")]
30 pub insecure: bool,
31
32 #[serde(default = "default_insecure_skip_verify")]
34 pub insecure_skip_verify: bool,
35}
36
37impl Default for TlsClientConfig {
38 fn default() -> Self {
39 TlsClientConfig {
40 config: Config::default(),
41 insecure: default_insecure(),
42 insecure_skip_verify: default_insecure_skip_verify(),
43 }
44 }
45}
46
47fn default_insecure() -> bool {
48 false
49}
50
51fn default_insecure_skip_verify() -> bool {
52 false
53}
54
55#[derive(Debug)]
58struct NoVerifier;
59
60impl ServerCertVerifier for NoVerifier {
61 fn verify_server_cert(
62 &self,
63 _: &CertificateDer<'_>,
64 _: &[CertificateDer<'_>],
65 _: &ServerName<'_>,
66 _: &[u8],
67 _: UnixTime,
68 ) -> Result<ServerCertVerified, Error> {
69 warn!("Skipping server cert verification");
70 Ok(ServerCertVerified::assertion())
71 }
72
73 fn verify_tls12_signature(
74 &self,
75 _: &[u8],
76 _: &CertificateDer<'_>,
77 _: &DigitallySignedStruct,
78 ) -> Result<HandshakeSignatureValid, Error> {
79 warn!("Skipping server cert verification - TLS 1.2");
80 Ok(HandshakeSignatureValid::assertion())
81 }
82
83 fn verify_tls13_signature(
84 &self,
85 _: &[u8],
86 _: &CertificateDer<'_>,
87 _: &DigitallySignedStruct,
88 ) -> Result<HandshakeSignatureValid, Error> {
89 warn!("Skipping server cert verification - TLS 1.3");
90 Ok(HandshakeSignatureValid::assertion())
91 }
92
93 fn supported_verify_schemes(&self) -> Vec<SignatureScheme> {
94 vec![
95 SignatureScheme::RSA_PKCS1_SHA1,
96 SignatureScheme::ECDSA_SHA1_Legacy,
97 SignatureScheme::RSA_PKCS1_SHA256,
98 SignatureScheme::ECDSA_NISTP256_SHA256,
99 SignatureScheme::RSA_PKCS1_SHA384,
100 SignatureScheme::ECDSA_NISTP384_SHA384,
101 SignatureScheme::RSA_PKCS1_SHA512,
102 SignatureScheme::ECDSA_NISTP521_SHA512,
103 SignatureScheme::RSA_PSS_SHA256,
104 SignatureScheme::RSA_PSS_SHA384,
105 SignatureScheme::RSA_PSS_SHA512,
106 SignatureScheme::ED25519,
107 SignatureScheme::ED448,
108 ]
109 }
110}
111
112impl TlsClientConfig {
114 pub fn new() -> Self {
116 TlsClientConfig::default()
117 }
118
119 pub fn with_insecure_skip_verify(self, insecure_skip_verify: bool) -> Self {
121 TlsClientConfig {
122 insecure_skip_verify,
123 ..self
124 }
125 }
126
127 pub fn with_insecure(self, insecure: bool) -> Self {
129 TlsClientConfig { insecure, ..self }
130 }
131
132 pub fn with_ca_file(self, ca_file: &str) -> Self {
134 TlsClientConfig {
135 config: self.config.with_ca_file(ca_file),
136 ..self
137 }
138 }
139
140 pub fn with_ca_pem(self, ca_pem: &str) -> Self {
142 TlsClientConfig {
143 config: self.config.with_ca_pem(ca_pem),
144 ..self
145 }
146 }
147
148 pub fn with_include_system_ca_certs_pool(self, include_system_ca_certs_pool: bool) -> Self {
150 TlsClientConfig {
151 config: self
152 .config
153 .with_include_system_ca_certs_pool(include_system_ca_certs_pool),
154 ..self
155 }
156 }
157
158 pub fn with_cert_file(self, cert_file: &str) -> Self {
160 TlsClientConfig {
161 config: self.config.with_cert_file(cert_file),
162 ..self
163 }
164 }
165
166 pub fn with_cert_pem(self, cert_pem: &str) -> Self {
168 TlsClientConfig {
169 config: self.config.with_cert_pem(cert_pem),
170 ..self
171 }
172 }
173
174 pub fn with_key_file(self, key_file: &str) -> Self {
176 TlsClientConfig {
177 config: self.config.with_key_file(key_file),
178 ..self
179 }
180 }
181
182 pub fn with_key_pem(self, key_pem: &str) -> Self {
184 TlsClientConfig {
185 config: self.config.with_key_pem(key_pem),
186 ..self
187 }
188 }
189
190 pub fn with_tls_version(self, tls_version: &str) -> Self {
192 TlsClientConfig {
193 config: self.config.with_tls_version(tls_version),
194 ..self
195 }
196 }
197
198 pub fn with_reload_interval(self, reload_interval: Option<std::time::Duration>) -> Self {
200 TlsClientConfig {
201 config: self.config.with_reload_interval(reload_interval),
202 ..self
203 }
204 }
205
206 fn load_rustls_client_config(
207 &self,
208 root_store: RootCertStore,
209 ) -> Result<RustlsClientConfig, ConfigError> {
210 use ConfigError::*;
211
212 let tls_version = match self.config.tls_version.as_str() {
214 "tls1.2" => &TLS12,
215 "tls1.3" => &TLS13,
216 _ => {
217 return Err(InvalidTlsVersion(self.config.tls_version.clone()));
219 }
220 };
221
222 let config_builder = RustlsClientConfig::builder_with_protocol_versions(&[tls_version])
224 .with_root_certificates(root_store);
225
226 let (cert, key) = match (
228 self.config.has_cert_file() && self.config.has_key_file(),
229 self.config.has_cert_pem() && self.config.has_key_pem(),
230 ) {
231 (true, true) => {
232 return Err(CannotUseBoth("cert".to_string()));
234 }
235 (false, false) => {
236 return Ok(config_builder.with_no_client_auth());
238 }
239 (true, false) => {
240 let cert = CertificateDer::from_pem_file(Path::new(
242 self.config.cert_file.as_ref().unwrap(),
243 ))
244 .map_err(InvalidPem)?;
245 let key =
246 PrivateKeyDer::from_pem_file(Path::new(self.config.key_file.as_ref().unwrap()))
247 .map_err(InvalidPem)?;
248 (cert, key)
249 }
250 (false, true) => {
251 let cert = CertificateDer::from_pem_slice(
253 self.config.cert_pem.as_ref().unwrap().as_bytes(),
254 )
255 .map_err(InvalidPem)?;
256 let key =
257 PrivateKeyDer::from_pem_slice(self.config.key_pem.as_ref().unwrap().as_bytes())
258 .map_err(InvalidPem)?;
259 (cert, key)
260 }
261 };
262
263 let client_config = config_builder
265 .with_client_auth_cert(vec![cert], key)
266 .map_err(ConfigBuilder)?;
267
268 Ok(client_config)
270 }
271}
272
273impl RustlsConfigLoader<RustlsClientConfig> for TlsClientConfig {
275 fn load_rustls_config(&self) -> Result<Option<RustlsClientConfig>, ConfigError> {
276 if self.insecure && !self.config.has_ca() {
277 return Ok(None);
278 }
279
280 let root_store = self.config.load_ca_cert_pool()?;
281 let mut client_config = self.load_rustls_client_config(root_store)?;
282
283 if self.insecure_skip_verify {
285 client_config
286 .dangerous()
287 .set_certificate_verifier(Arc::new(NoVerifier));
288 }
289
290 Ok(Some(client_config))
291 }
292}
293
294impl Configuration for TlsClientConfig {
295 fn validate(&self) -> Result<(), ConfigurationError> {
296 Ok(())
298 }
299}