aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlex Auvolat <alex@adnab.me>2021-12-08 12:02:39 +0100
committerAlex Auvolat <alex@adnab.me>2021-12-08 12:02:39 +0100
commit7599dfc0ef5b06d92eca8f9a954663e008a0b1fb (patch)
tree8d3c6402487e5397663cab2d35f77ed227c48390 /src
parentd7f3c13fa409ef2ee1ee78c18aae47e57383bec0 (diff)
downloadtricot-7599dfc0ef5b06d92eca8f9a954663e008a0b1fb.tar.gz
tricot-7599dfc0ef5b06d92eca8f9a954663e008a0b1fb.zip
Use self-signed certificates if necessary
Diffstat (limited to 'src')
-rw-r--r--src/cert_store.rs47
-rw-r--r--src/proxy_config.rs8
2 files changed, 47 insertions, 8 deletions
diff --git a/src/cert_store.rs b/src/cert_store.rs
index 8d45df4..4cc2fc0 100644
--- a/src/cert_store.rs
+++ b/src/cert_store.rs
@@ -19,6 +19,7 @@ use crate::proxy_config::*;
pub struct CertStore {
consul: Consul,
certs: RwLock<HashMap<String, Arc<Cert>>>,
+ self_signed_certs: RwLock<HashMap<String, Arc<Cert>>>,
rx_proxy_config: watch::Receiver<Arc<ProxyConfig>>,
}
@@ -27,6 +28,7 @@ impl CertStore {
Arc::new(Self {
consul,
certs: RwLock::new(HashMap::new()),
+ self_signed_certs: RwLock::new(HashMap::new()),
rx_proxy_config,
})
}
@@ -66,16 +68,23 @@ impl CertStore {
}
// Check in local memory if it exists
- let certs = self.certs.read().unwrap();
- if let Some(cert) = certs.get(domain) {
+ if let Some(cert) = self.certs.read().unwrap().get(domain) {
if !cert.is_old() {
return Ok(cert.clone());
}
}
- // Not found in local memory
+ // Not found in local memory, try to get it in background
tokio::spawn(self.clone().get_cert_task(domain.to_string()));
- bail!("Certificate not found (will try to get it in background)");
+
+ // In the meantime, use a self-signed certificate
+ if let Some(cert) = self.self_signed_certs.read().unwrap().get(domain) {
+ if !cert.is_old() {
+ return Ok(cert.clone());
+ }
+ }
+
+ self.gen_self_signed_certificate(domain)
}
pub async fn get_cert_task(self: Arc<Self>, domain: String) -> Result<Arc<Cert>> {
@@ -221,6 +230,27 @@ impl CertStore {
info!("Cert successfully renewed: {}", domain);
Ok(cert)
}
+
+ fn gen_self_signed_certificate(&self, domain: &str) -> Result<Arc<Cert>> {
+ let subject_alt_names = vec![domain.to_string(), "localhost".to_string()];
+ let cert = rcgen::generate_simple_self_signed(subject_alt_names)?;
+
+ let certser = CertSer {
+ hostname: domain.to_string(),
+ date: Utc::today().naive_utc(),
+ valid_days: 1024,
+ key_pem: cert.serialize_private_key_pem(),
+ cert_pem: cert.serialize_pem()?,
+ };
+ let cert = Arc::new(Cert::new(certser)?);
+ self.self_signed_certs
+ .write()
+ .unwrap()
+ .insert(domain.to_string(), cert.clone());
+ info!("Added self-signed certificate for {}", domain);
+
+ Ok(cert)
+ }
}
pub struct StoreResolver(pub Arc<CertStore>);
@@ -228,7 +258,12 @@ pub struct StoreResolver(pub Arc<CertStore>);
impl rustls::server::ResolvesServerCert for StoreResolver {
fn resolve(&self, client_hello: rustls::server::ClientHello<'_>) -> Option<Arc<CertifiedKey>> {
let domain = client_hello.server_name()?;
- let cert = self.0.get_cert_for_https(domain).ok()?;
- Some(cert.certkey.clone())
+ match self.0.get_cert_for_https(domain) {
+ Ok(cert) => Some(cert.certkey.clone()),
+ Err(e) => {
+ warn!("Could not get certificate for {}: {}", domain, e);
+ None
+ }
+ }
}
}
diff --git a/src/proxy_config.rs b/src/proxy_config.rs
index 2807a3b..1b46305 100644
--- a/src/proxy_config.rs
+++ b/src/proxy_config.rs
@@ -60,13 +60,17 @@ impl std::fmt::Display for ProxyEntry {
HostDescription::Hostname(h) => write!(f, "{}", h)?,
HostDescription::Pattern(p) => write!(f, "Pattern('{}')", p.as_str())?,
}
- write!(f, "{} {}", self.path_prefix.as_ref().unwrap_or(&String::new()), self.priority)?;
+ write!(
+ f,
+ "{} {}",
+ self.path_prefix.as_ref().unwrap_or(&String::new()),
+ self.priority
+ )?;
if !self.add_headers.is_empty() {
write!(f, "+Headers: {:?}", self.add_headers)?;
}
Ok(())
}
-
}
#[derive(Debug)]