forked from Deuxfleurs/tricot
60 lines
1.4 KiB
Rust
60 lines
1.4 KiB
Rust
|
use anyhow::Result;
|
||
|
|
||
|
use chrono::{Date, NaiveDate, Utc};
|
||
|
use rustls::sign::CertifiedKey;
|
||
|
use serde::{Deserialize, Serialize};
|
||
|
|
||
|
#[derive(Serialize, Deserialize, Debug)]
|
||
|
pub struct CertSer {
|
||
|
pub hostname: String,
|
||
|
pub date: NaiveDate,
|
||
|
pub valid_days: i64,
|
||
|
|
||
|
pub key_pem: String,
|
||
|
pub cert_pem: String,
|
||
|
}
|
||
|
|
||
|
pub struct Cert {
|
||
|
pub ser: CertSer,
|
||
|
|
||
|
pub certkey: CertifiedKey,
|
||
|
}
|
||
|
|
||
|
impl Cert {
|
||
|
pub fn new(ser: CertSer) -> Result<Self> {
|
||
|
let pem_certs = rustls_pemfile::read_all(&mut ser.cert_pem.as_bytes())?;
|
||
|
let certs = pem_certs
|
||
|
.into_iter()
|
||
|
.filter_map(|cert| match cert {
|
||
|
rustls_pemfile::Item::X509Certificate(cert) => Some(rustls::Certificate(cert)),
|
||
|
_ => None,
|
||
|
})
|
||
|
.collect::<Vec<_>>();
|
||
|
|
||
|
let pem_keys = rustls_pemfile::read_all(&mut ser.key_pem.as_bytes())?;
|
||
|
let keys = pem_keys
|
||
|
.into_iter()
|
||
|
.filter_map(|key| match key {
|
||
|
rustls_pemfile::Item::RSAKey(bytes) | rustls_pemfile::Item::PKCS8Key(bytes) => {
|
||
|
Some(rustls::sign::any_supported_type(&rustls::PrivateKey(bytes)).ok()?)
|
||
|
}
|
||
|
_ => None,
|
||
|
})
|
||
|
.collect::<Vec<_>>();
|
||
|
|
||
|
if keys.len() != 1 {
|
||
|
bail!("{} keys present in pem file", keys.len());
|
||
|
}
|
||
|
|
||
|
let certkey = CertifiedKey::new(certs, keys.into_iter().next().unwrap());
|
||
|
|
||
|
Ok(Cert { ser, certkey })
|
||
|
}
|
||
|
|
||
|
pub fn is_old(&self) -> bool {
|
||
|
let date = Date::<Utc>::from_utc(self.ser.date, Utc);
|
||
|
let today = Utc::today();
|
||
|
today - date > chrono::Duration::days(self.ser.valid_days / 2)
|
||
|
}
|
||
|
}
|