wip: started to implement reloader service

This commit is contained in:
Jun Kurihara 2024-05-27 11:55:22 +09:00
commit 377096c14e
No known key found for this signature in database
GPG key ID: 48ADFD173ED22B03
4 changed files with 82 additions and 64 deletions

View file

@ -9,19 +9,21 @@ use x509_parser::prelude::*;
type Certificate = rustls::pki_types::CertificateDer<'static>; type Certificate = rustls::pki_types::CertificateDer<'static>;
/// Raw private key in rustls format /// Raw private key in rustls format
type PrivateKey = pki_types::PrivateKeyDer<'static>; type PrivateKey = pki_types::PrivateKeyDer<'static>;
/// Subject Key ID in bytes
type SubjectKeyIdentifier = Vec<u8>;
/// Client CA trust anchors subject to the subject key identifier /// Client CA trust anchors subject to the subject key identifier
type TrustAnchors = HashMap<Vec<u8>, pki_types::TrustAnchor<'static>>; type TrustAnchors = HashMap<SubjectKeyIdentifier, pki_types::TrustAnchor<'static>>;
/* ------------------------------------------------ */ /* ------------------------------------------------ */
/// Raw certificates and private keys loaded from files for a single server name /// Raw certificates and private keys loaded from files for a single server name
#[derive(Debug, PartialEq, Eq, Clone)] #[derive(Debug, PartialEq, Eq, Clone)]
pub struct SingleServerCrypto { pub struct SingleServerCertsKeys {
certs: Vec<Certificate>, certs: Vec<Certificate>,
cert_keys: Arc<Vec<PrivateKey>>, cert_keys: Arc<Vec<PrivateKey>>,
client_ca_certs: Option<Vec<Certificate>>, client_ca_certs: Option<Vec<Certificate>>,
} }
impl SingleServerCrypto { impl SingleServerCertsKeys {
/// Create a new instance of SingleServerCrypto /// Create a new instance of SingleServerCrypto
pub fn new(certs: &[Certificate], cert_keys: &Arc<Vec<PrivateKey>>, client_ca_certs: &Option<Vec<Certificate>>) -> Self { pub fn new(certs: &[Certificate], cert_keys: &Arc<Vec<PrivateKey>>, client_ca_certs: &Option<Vec<Certificate>>) -> Self {
Self { Self {
@ -100,3 +102,57 @@ impl SingleServerCrypto {
Ok(trust_anchors) Ok(trust_anchors)
} }
} }
/* ------------------------------------------------ */
#[cfg(test)]
mod tests {
use super::super::*;
#[tokio::test]
async fn read_server_crt_key_files() {
let tls_cert_path = "../example-certs/server.crt";
let tls_cert_key_path = "../example-certs/server.key";
let crypto_file_source = CryptoFileSourceBuilder::default()
.tls_cert_key_path(tls_cert_key_path)
.tls_cert_path(tls_cert_path)
.build();
assert!(crypto_file_source.is_ok());
let crypto_file_source = crypto_file_source.unwrap();
let crypto_elem = crypto_file_source.read().await;
assert!(crypto_elem.is_ok());
let crypto_elem = crypto_elem.unwrap();
let certificed_key = crypto_elem.rustls_certified_key();
assert!(certificed_key.is_ok());
}
#[tokio::test]
async fn read_server_crt_key_files_with_client_ca_crt() {
let tls_cert_path = "../example-certs/server.crt";
let tls_cert_key_path = "../example-certs/server.key";
let client_ca_cert_path = Some("../example-certs/client.ca.crt");
let crypto_file_source = CryptoFileSourceBuilder::default()
.tls_cert_key_path(tls_cert_key_path)
.tls_cert_path(tls_cert_path)
.client_ca_cert_path(client_ca_cert_path)
.build();
assert!(crypto_file_source.is_ok());
let crypto_file_source = crypto_file_source.unwrap();
let crypto_elem = crypto_file_source.read().await;
assert!(crypto_elem.is_ok());
let crypto_elem = crypto_elem.unwrap();
assert!(crypto_elem.is_mutual_tls());
let certificed_key = crypto_elem.rustls_certified_key();
assert!(certificed_key.is_ok());
let trust_anchors = crypto_elem.rustls_trust_anchors();
assert!(trust_anchors.is_ok());
let trust_anchors = trust_anchors.unwrap();
assert_eq!(trust_anchors.len(), 1);
}
}

View file

@ -4,65 +4,12 @@ mod service;
mod source; mod source;
#[allow(unused_imports)] #[allow(unused_imports)]
pub(crate) mod log { mod log {
pub(crate) use tracing::{debug, error, info, warn}; pub(crate) use tracing::{debug, error, info, warn};
} }
pub use crate::{ pub use crate::{
certs::SingleServerCrypto, certs::SingleServerCertsKeys,
service::{ServerCrypto, ServerNameBytes, ServerNameCryptoMap},
source::{CryptoFileSource, CryptoFileSourceBuilder, CryptoFileSourceBuilderError, CryptoSource}, source::{CryptoFileSource, CryptoFileSourceBuilder, CryptoFileSourceBuilderError, CryptoSource},
}; };
/* ------------------------------------------------ */
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn read_server_crt_key_files() {
let tls_cert_path = "../example-certs/server.crt";
let tls_cert_key_path = "../example-certs/server.key";
let crypto_file_source = CryptoFileSourceBuilder::default()
.tls_cert_key_path(tls_cert_key_path)
.tls_cert_path(tls_cert_path)
.build();
assert!(crypto_file_source.is_ok());
let crypto_file_source = crypto_file_source.unwrap();
let crypto_elem = crypto_file_source.read().await;
assert!(crypto_elem.is_ok());
let crypto_elem = crypto_elem.unwrap();
let certificed_key = crypto_elem.rustls_certified_key();
assert!(certificed_key.is_ok());
}
#[tokio::test]
async fn read_server_crt_key_files_with_client_ca_crt() {
let tls_cert_path = "../example-certs/server.crt";
let tls_cert_key_path = "../example-certs/server.key";
let client_ca_cert_path = Some("../example-certs/client.ca.crt");
let crypto_file_source = CryptoFileSourceBuilder::default()
.tls_cert_key_path(tls_cert_key_path)
.tls_cert_path(tls_cert_path)
.client_ca_cert_path(client_ca_cert_path)
.build();
assert!(crypto_file_source.is_ok());
let crypto_file_source = crypto_file_source.unwrap();
let crypto_elem = crypto_file_source.read().await;
assert!(crypto_elem.is_ok());
let crypto_elem = crypto_elem.unwrap();
assert!(crypto_elem.is_mutual_tls());
let certificed_key = crypto_elem.rustls_certified_key();
assert!(certificed_key.is_ok());
let trust_anchors = crypto_elem.rustls_trust_anchors();
assert!(trust_anchors.is_ok());
let trust_anchors = trust_anchors.unwrap();
assert_eq!(trust_anchors.len(), 1);
}
}

View file

@ -0,0 +1,15 @@
use rustc_hash::FxHashMap as HashMap;
use rustls::ServerConfig;
use std::sync::Arc;
/// ServerName in bytes type
pub type ServerNameBytes = Vec<u8>;
/// ServerName (SNI) to ServerConfig map type
pub type ServerNameCryptoMap = HashMap<ServerNameBytes, Arc<ServerConfig>>;
/// ServerName (SNI) to ServerConfig map
pub struct ServerCrypto {
// For Quic/HTTP3, only servers with no client authentication
pub inner_global_no_client_auth: Arc<ServerConfig>,
// // For TLS over TCP/HTTP2 and 1.1, map of SNI to server_crypto for all given servers
pub inner_local_map: Arc<ServerNameCryptoMap>,
}

View file

@ -1,4 +1,4 @@
use crate::{certs::SingleServerCrypto, error::*, log::*}; use crate::{certs::SingleServerCertsKeys, error::*, log::*};
use async_trait::async_trait; use async_trait::async_trait;
use derive_builder::Builder; use derive_builder::Builder;
use std::{ use std::{
@ -15,7 +15,7 @@ pub trait CryptoSource {
type Error; type Error;
/// read crypto materials from source /// read crypto materials from source
async fn read(&self) -> Result<SingleServerCrypto, Self::Error>; async fn read(&self) -> Result<SingleServerCertsKeys, Self::Error>;
/// 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;
@ -58,7 +58,7 @@ impl CryptoFileSourceBuilder {
impl CryptoSource for CryptoFileSource { impl CryptoSource for CryptoFileSource {
type Error = RpxyCertError; type Error = RpxyCertError;
/// read crypto materials from source /// read crypto materials from source
async fn read(&self) -> Result<SingleServerCrypto, Self::Error> { async fn read(&self) -> Result<SingleServerCertsKeys, Self::Error> {
read_certs_and_keys( read_certs_and_keys(
&self.tls_cert_path, &self.tls_cert_path,
&self.tls_cert_key_path, &self.tls_cert_key_path,
@ -77,7 +77,7 @@ fn read_certs_and_keys(
cert_path: &PathBuf, cert_path: &PathBuf,
cert_key_path: &PathBuf, cert_key_path: &PathBuf,
client_ca_cert_path: Option<&PathBuf>, client_ca_cert_path: Option<&PathBuf>,
) -> Result<SingleServerCrypto, RpxyCertError> { ) -> Result<SingleServerCertsKeys, RpxyCertError> {
debug!("Read TLS server certificates and private key"); debug!("Read TLS server certificates and private key");
// certificates // certificates
@ -152,7 +152,7 @@ fn read_certs_and_keys(
None None
}; };
Ok(SingleServerCrypto::new( Ok(SingleServerCertsKeys::new(
&raw_certs, &raw_certs,
&Arc::new(raw_cert_keys), &Arc::new(raw_cert_keys),
&client_ca_certs, &client_ca_certs,