Skip to main content

synapse_mtls/
server.rs

1use crate::certs::{load_certs, load_private_key};
2use anyhow::{Context, Result};
3use rustls::{RootCertStore, ServerConfig, server::WebPkiClientVerifier};
4use std::{path::Path, sync::Arc};
5use tokio_rustls::TlsAcceptor;
6use tracing::info;
7
8/// Build a TLS acceptor for server-side mTLS
9///
10/// This configures the server to:
11/// - Present a server certificate to clients
12/// - Require client certificates (mTLS)
13/// - Verify client certificates against the CA
14pub fn build_mtls_acceptor<P: AsRef<Path>>(
15    server_cert_path: P,
16    server_key_path: P,
17    ca_cert_path: P,
18) -> Result<TlsAcceptor> {
19    info!(
20        "Building server mTLS acceptor: cert={}, key={}, ca={}",
21        server_cert_path.as_ref().display(),
22        server_key_path.as_ref().display(),
23        ca_cert_path.as_ref().display()
24    );
25
26    // Load server certificate
27    let certs = load_certs(&server_cert_path)?;
28    info!("Loaded {} server certificate(s)", certs.len());
29
30    // Load server private key
31    let key = load_private_key(&server_key_path)?;
32    info!("Server private key loaded");
33
34    // Load CA certificate for client verification
35    let ca_certs = load_certs(&ca_cert_path)?;
36
37    // Build root certificate store for client verification
38    let mut root_store = RootCertStore::empty();
39    for cert in ca_certs {
40        root_store
41            .add(cert)
42            .context("Failed to add CA cert to root store")?;
43    }
44    info!(
45        "CA certificate loaded, {} root certs in store",
46        root_store.len()
47    );
48
49    // Build client verifier that requires valid client certificates
50    let client_verifier = WebPkiClientVerifier::builder(Arc::new(root_store))
51        .build()
52        .context("Failed to build client verifier")?;
53
54    // Build server config with mandatory client authentication
55    let mut config = ServerConfig::builder()
56        .with_client_cert_verifier(client_verifier)
57        .with_single_cert(certs, key)
58        .context("Failed to build TLS server config")?;
59
60    // Enable HTTP/2 via ALPN
61    config.alpn_protocols = vec![b"h2".to_vec(), b"http/1.1".to_vec()];
62
63    info!("Server TLS configuration built successfully (HTTP/2 + HTTP/1.1 via ALPN)");
64    Ok(TlsAcceptor::from(Arc::new(config)))
65}