fix: inappropriate location of CertsAndKeys implementations

This commit is contained in:
Jun Kurihara 2023-07-18 15:36:35 +09:00
commit 15e8659633
No known key found for this signature in database
GPG key ID: D992B3E3DE1DED23
2 changed files with 81 additions and 80 deletions

View file

@ -1,13 +1,11 @@
use async_trait::async_trait; use async_trait::async_trait;
use rustls::{Certificate, PrivateKey}; use rustc_hash::FxHashSet as HashSet;
use rustls::{
/// Certificates and private keys in rustls loaded from files sign::{any_supported_type, CertifiedKey},
#[derive(Debug, PartialEq, Eq, Clone)] Certificate, OwnedTrustAnchor, PrivateKey,
pub struct CertsAndKeys { };
pub certs: Vec<Certificate>, use std::io;
pub cert_keys: Vec<PrivateKey>, use x509_parser::prelude::*;
pub client_ca_certs: Option<Vec<Certificate>>,
}
#[async_trait] #[async_trait]
// Trait to read certs and keys anywhere from KVS, file, sqlite, etc. // Trait to read certs and keys anywhere from KVS, file, sqlite, etc.
@ -20,3 +18,74 @@ pub trait CryptoSource {
/// Returns true when mutual tls is enabled /// Returns true when mutual tls is enabled
fn is_mutual_tls(&self) -> bool; fn is_mutual_tls(&self) -> bool;
} }
/// Certificates and private keys in rustls loaded from files
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct CertsAndKeys {
pub certs: Vec<Certificate>,
pub cert_keys: Vec<PrivateKey>,
pub client_ca_certs: Option<Vec<Certificate>>,
}
impl CertsAndKeys {
pub fn parse_server_certs_and_keys(&self) -> Result<CertifiedKey, anyhow::Error> {
// for (server_name_bytes_exp, certs_and_keys) in self.inner.iter() {
let signing_key = self
.cert_keys
.iter()
.find_map(|k| {
if let Ok(sk) = any_supported_type(k) {
Some(sk)
} else {
None
}
})
.ok_or_else(|| {
io::Error::new(
io::ErrorKind::InvalidInput,
"Unable to find a valid certificate and key",
)
})?;
Ok(CertifiedKey::new(self.certs.clone(), signing_key))
}
pub fn parse_client_ca_certs(&self) -> Result<(Vec<OwnedTrustAnchor>, HashSet<Vec<u8>>), anyhow::Error> {
let certs = self.client_ca_certs.as_ref().ok_or(anyhow::anyhow!("No client cert"))?;
let owned_trust_anchors: Vec<_> = certs
.iter()
.map(|v| {
// let trust_anchor = tokio_rustls::webpki::TrustAnchor::try_from_cert_der(&v.0).unwrap();
let trust_anchor = webpki::TrustAnchor::try_from_cert_der(&v.0).unwrap();
rustls::OwnedTrustAnchor::from_subject_spki_name_constraints(
trust_anchor.subject,
trust_anchor.spki,
trust_anchor.name_constraints,
)
})
.collect();
// TODO: SKID is not used currently
let subject_key_identifiers: HashSet<_> = certs
.iter()
.filter_map(|v| {
// retrieve ca key id (subject key id)
let cert = parse_x509_certificate(&v.0).unwrap().1;
let subject_key_ids = cert
.iter_extensions()
.filter_map(|ext| match ext.parsed_extension() {
ParsedExtension::SubjectKeyIdentifier(skid) => Some(skid),
_ => None,
})
.collect::<Vec<_>>();
if !subject_key_ids.is_empty() {
Some(subject_key_ids[0].0.to_owned())
} else {
None
}
})
.collect();
Ok((owned_trust_anchors, subject_key_identifiers))
}
}

View file

@ -6,14 +6,9 @@ use crate::{
}; };
use async_trait::async_trait; use async_trait::async_trait;
use hot_reload::*; use hot_reload::*;
use rustc_hash::{FxHashMap as HashMap, FxHashSet as HashSet}; use rustc_hash::FxHashMap as HashMap;
use rustls::{ use rustls::{server::ResolvesServerCertUsingSni, sign::CertifiedKey, RootCertStore, ServerConfig};
server::ResolvesServerCertUsingSni, use std::sync::Arc;
sign::{any_supported_type, CertifiedKey},
OwnedTrustAnchor, RootCertStore, ServerConfig,
};
use std::{io, sync::Arc};
use x509_parser::prelude::*;
#[derive(Clone)] #[derive(Clone)]
/// Reloader service for certificates and keys for TLS /// Reloader service for certificates and keys for TLS
@ -69,69 +64,6 @@ where
} }
} }
impl CertsAndKeys {
fn parse_server_certs_and_keys(&self) -> Result<CertifiedKey, anyhow::Error> {
// for (server_name_bytes_exp, certs_and_keys) in self.inner.iter() {
let signing_key = self
.cert_keys
.iter()
.find_map(|k| {
if let Ok(sk) = any_supported_type(k) {
Some(sk)
} else {
None
}
})
.ok_or_else(|| {
io::Error::new(
io::ErrorKind::InvalidInput,
"Unable to find a valid certificate and key",
)
})?;
Ok(CertifiedKey::new(self.certs.clone(), signing_key))
}
pub fn parse_client_ca_certs(&self) -> Result<(Vec<OwnedTrustAnchor>, HashSet<Vec<u8>>), anyhow::Error> {
let certs = self.client_ca_certs.as_ref().ok_or(anyhow::anyhow!("No client cert"))?;
let owned_trust_anchors: Vec<_> = certs
.iter()
.map(|v| {
// let trust_anchor = tokio_rustls::webpki::TrustAnchor::try_from_cert_der(&v.0).unwrap();
let trust_anchor = webpki::TrustAnchor::try_from_cert_der(&v.0).unwrap();
rustls::OwnedTrustAnchor::from_subject_spki_name_constraints(
trust_anchor.subject,
trust_anchor.spki,
trust_anchor.name_constraints,
)
})
.collect();
// TODO: SKID is not used currently
let subject_key_identifiers: HashSet<_> = certs
.iter()
.filter_map(|v| {
// retrieve ca key id (subject key id)
let cert = parse_x509_certificate(&v.0).unwrap().1;
let subject_key_ids = cert
.iter_extensions()
.filter_map(|ext| match ext.parsed_extension() {
ParsedExtension::SubjectKeyIdentifier(skid) => Some(skid),
_ => None,
})
.collect::<Vec<_>>();
if !subject_key_ids.is_empty() {
Some(subject_key_ids[0].0.to_owned())
} else {
None
}
})
.collect();
Ok((owned_trust_anchors, subject_key_identifiers))
}
}
impl TryInto<Arc<ServerCrypto>> for &ServerCryptoBase { impl TryInto<Arc<ServerCrypto>> for &ServerCryptoBase {
type Error = anyhow::Error; type Error = anyhow::Error;