use std::sync::Arc;
use crate::{host::HostImpl, VetisHosts};
use rustls::{
pki_types::{CertificateDer, PrivateKeyDer},
server::ResolvesServerCertUsingSni,
sign::CertifiedKey,
ServerConfig,
};
use vetis::{
errors::{StartError, VetisError},
host::Host,
};
pub struct TlsFactory {}
impl TlsFactory {
pub async fn create_tls_config(
hosts: VetisHosts<HostImpl>,
alpn_protocols: Vec<Vec<u8>>,
) -> Result<Option<ServerConfig>, VetisError> {
let hosts = hosts.clone();
#[cfg(feature = "__rustls_awc_lc_rs")]
let provider = rustls::crypto::aws_lc_rs::default_provider();
#[cfg(feature = "__rustls_ring")]
let provider = rustls::crypto::ring::default_provider();
let mut resolver = ResolvesServerCertUsingSni::new();
let hosts = hosts.read().await;
for (hostname, host) in hosts.iter() {
if let Some(security) = host
.config()
.security()
{
let cert = security.cert();
let key = security.key();
let cert = CertificateDer::from(cert.to_vec());
let mut chain = vec![cert];
if let Some(ca_cert) = security.ca_cert() {
let ca_cert = CertificateDer::from(ca_cert.to_vec());
chain.push(ca_cert);
}
let key = PrivateKeyDer::try_from(key.to_vec())
.map_err(|_| VetisError::Tls("Failed to parse private key".to_string()))?;
let certified_key = CertifiedKey::from_der(chain, key, &provider).map_err(|e| {
VetisError::Tls(format!("Failed to create certified key: {}", e))
})?;
let hostname = hostname.clone();
resolver
.add(&hostname, certified_key)
.map_err(|e| VetisError::Tls(e.to_string()))?;
}
}
let builder = rustls::ServerConfig::builder_with_provider(Arc::new(provider))
.with_protocol_versions(rustls::ALL_VERSIONS)
.map_err(|e| VetisError::Start(StartError::Tls(e.to_string())))?;
let mut tls_config = builder
.with_no_client_auth()
.with_cert_resolver(Arc::new(resolver));
tls_config.max_early_data_size = u32::MAX;
tls_config.alpn_protocols = alpn_protocols;
Ok(Some(tls_config))
}
}