aboutsummaryrefslogblamecommitdiff
path: root/src/cert.rs
blob: de0d821894d3557ad13c0495794fa41db2364fd5 (plain) (tree)


























































                                                                                                                
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)
	}
}