scratchstack_config/
tls.rs

1use {
2    crate::error::{ConfigError, TlsConfigErrorKind},
3    rustls::ServerConfig,
4    rustls_pemfile::{certs, rsa_private_keys},
5    rustls_pki_types::{CertificateDer, PrivateKeyDer},
6    serde::Deserialize,
7    std::{
8        fmt::Debug,
9        fs::File,
10        io::{BufRead, BufReader},
11    },
12};
13
14#[derive(Clone, Deserialize, Debug)]
15pub struct TlsConfig {
16    pub certificate_chain_file: String,
17    pub private_key_file: String,
18}
19
20impl TlsConfig {
21    /// Resolve files referenced in the TLS configuration to actual certificates and keys.
22    pub fn to_server_config(&self) -> Result<ServerConfig, ConfigError> {
23        let builder = ServerConfig::builder().with_no_client_auth();
24
25        let cert_file = File::open(&self.certificate_chain_file)?;
26        let mut reader = BufReader::new(cert_file);
27        let certs = read_certs(&mut reader)?;
28        if certs.is_empty() {
29            return Err(TlsConfigErrorKind::InvalidCertificate.into());
30        }
31
32        let private_key_file = File::open(&self.private_key_file)?;
33        let mut reader = BufReader::new(private_key_file);
34        let mut private_keys = read_rsa_private_keys(&mut reader)?;
35        if private_keys.len() != 1 {
36            return Err(TlsConfigErrorKind::InvalidPrivateKey.into());
37        }
38        let private_key = private_keys.remove(0);
39
40        builder
41            .with_single_cert(certs, private_key)
42            .map_err(|e| ConfigError::InvalidTlsConfig(TlsConfigErrorKind::TlsSetupFailed(e)))
43    }
44}
45
46/// Extract all the certificates from `r` and return a [`Vec<CertificateDers>`][rustls_pki_types::CertificateDer]
47/// containing the der-format contents.
48fn read_certs(r: &mut dyn BufRead) -> Result<Vec<CertificateDer<'static>>, ConfigError> {
49    let mut result = Vec::with_capacity(2);
50    for maybe_cert in certs(r) {
51        result.push(maybe_cert?);
52    }
53    Ok(result)
54}
55
56/// Extract all RSA private keys from `r` and return a `Vec<PrivateKeyDer>`[rustls_pki_types::PrivateKeyDer]
57/// containing the der-format contents.
58fn read_rsa_private_keys(r: &mut dyn BufRead) -> Result<Vec<PrivateKeyDer<'static>>, ConfigError> {
59    let mut result = Vec::with_capacity(1);
60    for maybe_key in rsa_private_keys(r) {
61        result.push(maybe_key?.into());
62    }
63    Ok(result)
64}