cloudiful_server/core/
tls.rs1use std::{fs::File, io::BufReader, sync::Arc};
2
3use crate::core::{
4 ValidatedServerConfig,
5 error::{ServerError, TlsConfigLoadError},
6};
7
8pub fn load_tls_config<U>(
9 config: &ValidatedServerConfig<U>,
10) -> Result<Option<rustls::ServerConfig>, ServerError> {
11 let Some(tls) = config.tls.as_ref() else {
12 return Ok(None);
13 };
14
15 let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
16
17 let mut cert_file = BufReader::new(File::open(&tls.cert_path).map_err(|source| {
18 ServerError::Tls(TlsConfigLoadError::OpenCertificate {
19 path: tls.cert_path.clone(),
20 source,
21 })
22 })?);
23
24 let mut key_file = BufReader::new(File::open(&tls.cert_key_path).map_err(|source| {
25 ServerError::Tls(TlsConfigLoadError::OpenPrivateKey {
26 path: tls.cert_key_path.clone(),
27 source,
28 })
29 })?);
30
31 let tls_certs = rustls_pemfile::certs(&mut cert_file)
32 .collect::<Result<Vec<_>, _>>()
33 .map_err(|source| {
34 ServerError::Tls(TlsConfigLoadError::ReadCertificates {
35 path: tls.cert_path.clone(),
36 source,
37 })
38 })?;
39
40 let tls_key = rustls_pemfile::private_key(&mut key_file)
41 .map_err(|source| {
42 ServerError::Tls(TlsConfigLoadError::ReadPrivateKey {
43 path: tls.cert_key_path.clone(),
44 source,
45 })
46 })?
47 .ok_or_else(|| {
48 ServerError::Tls(TlsConfigLoadError::MissingPrivateKey {
49 path: tls.cert_key_path.clone(),
50 })
51 })?;
52
53 let builder = rustls::ServerConfig::builder();
54 let builder = match tls.client_ca.as_ref() {
55 Some(client_ca_path) => {
56 let mut client_ca_file =
57 BufReader::new(File::open(client_ca_path).map_err(|source| {
58 ServerError::Tls(TlsConfigLoadError::OpenClientCa {
59 path: client_ca_path.clone(),
60 source,
61 })
62 })?);
63
64 let client_ca_certs = rustls_pemfile::certs(&mut client_ca_file)
65 .collect::<Result<Vec<_>, _>>()
66 .map_err(|source| {
67 ServerError::Tls(TlsConfigLoadError::ReadClientCa {
68 path: client_ca_path.clone(),
69 source,
70 })
71 })?;
72
73 let mut client_roots = rustls::RootCertStore::empty();
74 let (added, _ignored) = client_roots.add_parsable_certificates(client_ca_certs);
75 if added == 0 {
76 return Err(ServerError::Tls(TlsConfigLoadError::InvalidClientCa {
77 path: client_ca_path.clone(),
78 source: rustls::Error::General("no valid client CA certificates found".into()),
79 }));
80 }
81
82 let client_verifier =
83 rustls::server::WebPkiClientVerifier::builder(Arc::new(client_roots))
84 .build()
85 .map_err(|source| {
86 ServerError::Tls(TlsConfigLoadError::InvalidClientCa {
87 path: client_ca_path.clone(),
88 source: rustls::Error::General(source.to_string().into()),
89 })
90 })?;
91
92 builder.with_client_cert_verifier(client_verifier)
93 }
94 None => builder.with_no_client_auth(),
95 };
96
97 builder
98 .with_single_cert(tls_certs, tls_key)
99 .map(Some)
100 .map_err(|source| ServerError::Tls(TlsConfigLoadError::InvalidConfig { source }))
101}