kutil_http/tls/
container.rs1use super::{error::*, pem::*, resolver::*};
2
3use {
4 bytestring::*,
5 kutil_std::collections::*,
6 rustls::{crypto::*, server::*, sign::*},
7 std::sync::*,
8};
9
10#[derive(Clone, Debug, Default)]
16pub struct TlsContainer {
17 targets: FastHashMap<ByteString, SniResolverTarget>,
18}
19
20impl TlsContainer {
21 pub fn is_empty(&self) -> bool {
23 self.targets.is_empty()
24 }
25
26 pub fn add_key(&mut self, sni: ByteString, certified_key: Arc<CertifiedKey>) -> Result<(), TlsContainerError> {
28 if self.targets.contains_key(&sni) {
29 return Err(format!("already has a target for: {}", sni).into());
30 }
31
32 self.targets.insert(sni, SniResolverTarget::Key(certified_key));
33 Ok(())
34 }
35
36 pub fn add_delegate(
38 &mut self,
39 sni: ByteString,
40 resolver: Arc<dyn ResolvesServerCert>,
41 ) -> Result<(), TlsContainerError> {
42 if self.targets.contains_key(&sni) {
43 return Err(format!("already has a target for: {}", sni).into());
44 }
45
46 self.targets.insert(sni, SniResolverTarget::Delegate(resolver));
47 Ok(())
48 }
49
50 pub fn add_key_from_pem(
52 &mut self,
53 sni: ByteString,
54 certificates_pem: &[u8],
55 private_key_pem: &[u8],
56 ) -> Result<(), TlsContainerError> {
57 if self.targets.contains_key(&sni) {
58 return Err(format!("already has a target for: {}", sni).into());
59 }
60
61 self.targets.insert(
62 sni,
63 SniResolverTarget::Key(Arc::new(
64 certified_key_from_pem(certificates_pem, private_key_pem).map_err(TlsContainerError::new_from)?,
65 )),
66 );
67 Ok(())
68 }
69
70 pub fn http_server_config(&self) -> Result<ServerConfig, TlsContainerError> {
78 let provider = aws_lc_rs::default_provider();
79
80 let mut server_config = ServerConfig::builder_with_provider(provider.into())
81 .with_safe_default_protocol_versions()
82 .expect("builder")
83 .with_no_client_auth()
84 .with_cert_resolver(Arc::new(self.resolver()?));
85
86 server_config.alpn_protocols = vec!["h2".into(), "http/1.1".into()];
87
88 Ok(server_config)
89 }
90
91 pub fn resolver(&self) -> Result<SniResolver, TlsContainerError> {
93 if self.targets.is_empty() {
94 Err("no targets".into())
95 } else {
96 Ok(if self.targets.len() == 1 {
97 SniResolver::Single(self.targets.values().next().expect("not empty").clone())
98 } else {
99 SniResolver::BySNI(self.targets.clone())
100 })
101 }
102 }
103}