kumo_server_common/
tls_helpers.rs

1use anyhow::Context;
2use data_loader::KeySource;
3use rustls::pki_types::pem::PemObject;
4use rustls::pki_types::{CertificateDer, PrivateKeyDer, PrivatePkcs8KeyDer};
5use rustls::server::WebPkiClientVerifier;
6use rustls::{RootCertStore, ServerConfig};
7use std::sync::Arc;
8
9fn read_trust_anchor(trust_anchor: &[u8]) -> anyhow::Result<RootCertStore> {
10    let mut store = RootCertStore::empty();
11    let mut added = 0;
12    for cert in CertificateDer::pem_slice_iter(trust_anchor) {
13        store.add(cert?)?;
14        added += 1;
15    }
16
17    if added == 0 {
18        anyhow::bail!("failed to parse certs");
19    }
20
21    Ok(store)
22}
23
24pub async fn make_server_config(
25    hostname: &str,
26    tls_private_key: &Option<KeySource>,
27    tls_certificate: &Option<KeySource>,
28    required_client_ca: &Option<KeySource>,
29) -> anyhow::Result<Arc<ServerConfig>> {
30    let mut certificates = vec![];
31    let private_key = match tls_private_key {
32        Some(key) => PrivateKeyDer::from_pem_slice(&key.get().await?)
33            .with_context(|| format!("loading private key from {key:?}"))?,
34        None => {
35            let key = rcgen::generate_simple_self_signed(vec![hostname.to_string()])?;
36            certificates.push(CertificateDer::from_slice(key.cert.der()).into_owned());
37            PrivateKeyDer::from(PrivatePkcs8KeyDer::from(key.key_pair.serialize_der()))
38        }
39    };
40
41    if let Some(cert_file) = tls_certificate {
42        let data = cert_file.get().await?;
43        certificates = CertificateDer::pem_slice_iter(&data)
44            .collect::<Result<Vec<_>, _>>()
45            .with_context(|| format!("loading certificates from {cert_file:?}"))?;
46    }
47
48    let config = ServerConfig::builder();
49    let config = match required_client_ca {
50        Some(client_ca) => {
51            let ca = client_ca.get().await?;
52            let verifier = WebPkiClientVerifier::builder(read_trust_anchor(&ca)?.into()).build()?;
53            config.with_client_cert_verifier(verifier)
54        }
55        None => config.with_no_client_auth(),
56    };
57    let config = config.with_single_cert(certificates, private_key)?;
58
59    Ok(Arc::new(config))
60}