feat: config works

This commit is contained in:
2024-03-30 15:37:26 +08:00
parent f02f6bb7dd
commit 55c1aa3205
8 changed files with 944 additions and 182 deletions

View File

@@ -1,61 +1,35 @@
use std::collections::HashMap;
use std::fs;
use once_cell::sync::Lazy;
use rcgen::{Certificate, CertificateParams, DnType, ExtendedKeyUsagePurpose, IsCa, KeyPair, KeyUsagePurpose};
use time::{Duration, OffsetDateTime};
use tokio::sync::RwLock;
const INTERMEDIATE_CERT_ENV_VAR: &str = "INTERMEDIATE_CERT";
const INTERMEDIATE_KEY_ENV_VAR: &str = "INTERMEDIATE_KEY";
static INTERMEDIATE_CA: Lazy<(Certificate, String)> = Lazy::new(|| {
let cert_fn = std::env::var(INTERMEDIATE_CERT_ENV_VAR)
.unwrap_or("__ignore_intermediate_cert.pem".to_string());
let key_fn = std::env::var(INTERMEDIATE_KEY_ENV_VAR)
.unwrap_or("__ignore_intermediate_pri_key.pem".to_string());
let cert_pem = fs::read_to_string(cert_fn).expect("Read cert file failed");
let key_pem = fs::read_to_string(key_fn).expect("Read key file failed");
let key_pem = parse_pkcs8(&key_pem);
let key_pair = KeyPair::from_pem(&key_pem).expect("Parse keypair failed");
// 底层逻辑限制P256 与 SHA256 搭配P384 与 SHA384 搭配
let certificate_params = CertificateParams::from_ca_cert_pem(&cert_pem, key_pair)
.expect("Cert and keypair mismatch");
let cert = Certificate::from_params(certificate_params)
.expect("Parse cert params failed");
(cert, cert_pem)
});
#[derive(Debug, Clone)]
pub struct Cert {
pub cert_pem: String,
pub intermediate_pem: String,
pub key_pem: String,
}
static CERTIFICATE_CACHE_MAP: Lazy<RwLock<HashMap<String, Cert>>> = Lazy::new(|| {
RwLock::new(HashMap::new())
});
pub fn load_certificate(cert_fn: &str, key_fn: &str) -> Result<(Certificate, String), String> {
let cert_pem = fs::read_to_string(cert_fn).map_err(|e| format!("Read file: {} failed: {}", cert_fn, e))?;
let key_pem = fs::read_to_string(key_fn).map_err(|e| format!("Read file: {} failed: {}", key_fn, e))?;
let key_pem = parse_pkcs8(&key_pem);
let key_pair = KeyPair::from_pem(&key_pem).map_err(|e| format!("Parse key: {} failed: {}", key_fn, e))?;
// 底层逻辑限制P256 与 SHA256 搭配P384 与 SHA384 搭配
let certificate_params = CertificateParams::from_ca_cert_pem(&cert_pem, key_pair)
.map_err(|e| format!("Cert and keypair match failed: {}", e))?;
let cert = Certificate::from_params(certificate_params)
.map_err(|e| format!("Parse cert params failed: {}", e))?;
Ok((cert, cert_pem))
}
pub async fn issue_certificate(domain: &str) -> Cert {
{
if let Some(cert) = CERTIFICATE_CACHE_MAP.read().await.get(domain) {
return cert.clone();
}
}
let cert = new_end_entity(domain);
let cert_pem = cert.serialize_pem_with_signer(&INTERMEDIATE_CA.0).expect("Sign cert failed");
pub fn issue_certificate(intermediate_certificate: &Certificate, domain: &str) -> Result<Cert, String> {
let cert = new_end_entity(domain)?;
let cert_pem = cert.serialize_pem_with_signer(intermediate_certificate).map_err(|e| format!("Sign cert failed: {}", e))?;
let key_pem = cert.serialize_private_key_pem();
let intermediate_pem = INTERMEDIATE_CA.1.clone();
let cert = Cert {
Ok(Cert {
cert_pem,
intermediate_pem,
key_pem,
};
{
CERTIFICATE_CACHE_MAP.write().await.insert(domain.to_string(), cert.clone());
}
cert
})
}
fn parse_pkcs8(pem: &str) -> String {
@@ -89,9 +63,9 @@ fn parse_pkcs8(pem: &str) -> String {
pem.to_string()
}
fn new_end_entity(domain: &str) -> Certificate {
fn new_end_entity(domain: &str) -> Result<Certificate, String> {
let mut params = CertificateParams::new(vec![domain.into()]);
let (start, end) = validity_period();
let (start, end) = validity_period()?;
params.distinguished_name.push(DnType::CommonName, domain);
params.use_authority_key_identifier_extension = true;
params.key_usages.push(KeyUsagePurpose::DigitalSignature);
@@ -100,11 +74,11 @@ fn new_end_entity(domain: &str) -> Certificate {
params.extended_key_usages.push(ExtendedKeyUsagePurpose::ClientAuth);
params.not_before = start;
params.not_after = end;
Certificate::from_params(params).expect("Generate domain certificate failed")
Ok(Certificate::from_params(params).map_err(|e| format!("New cert failed: {}", e))?)
}
fn validity_period() -> (OffsetDateTime, OffsetDateTime) {
let start = OffsetDateTime::now_utc().checked_sub(Duration::hours(1)).unwrap();
let end = OffsetDateTime::now_utc().checked_add(Duration::days(90)).unwrap();
(start, end)
fn validity_period() -> Result<(OffsetDateTime, OffsetDateTime), String> {
let start = OffsetDateTime::now_utc().checked_sub(Duration::hours(1)).expect("SHOULD NOT HAPPEN!");
let end = OffsetDateTime::now_utc().checked_add(Duration::days(90)).expect("SHOULD NOT HAPPEN!");
Ok((start, end))
}