use super::parse_leaf_chain_certificates;
use pingora::tls::x509::X509;
use std::sync::LazyLock;
const E5: &[u8] = include_bytes!("../assets/e5.pem");
const E6: &[u8] = include_bytes!("../assets/e6.pem");
const R10: &[u8] = include_bytes!("../assets/r10.pem");
const R11: &[u8] = include_bytes!("../assets/r11.pem");
const EXPIRATION_BUFFER_DAYS: u64 = 30;
const SECONDS_PER_DAY: u64 = 24 * 3600;
fn parse_chain_certificate(data: &[u8]) -> Option<X509> {
let expiration_threshold =
pingap_core::now_sec() + EXPIRATION_BUFFER_DAYS * SECONDS_PER_DAY;
String::from_utf8(data.to_vec())
.ok()
.and_then(|pem_str| parse_leaf_chain_certificates(&pem_str, "").ok())
.filter(|(cert, _)| cert.not_after > expiration_threshold as i64)
.and_then(|_| X509::from_pem(data).ok())
}
static E5_CERTIFICATE: LazyLock<Option<X509>> =
LazyLock::new(|| parse_chain_certificate(E5));
static E6_CERTIFICATE: LazyLock<Option<X509>> =
LazyLock::new(|| parse_chain_certificate(E6));
static R10_CERTIFICATE: LazyLock<Option<X509>> =
LazyLock::new(|| parse_chain_certificate(R10));
static R11_CERTIFICATE: LazyLock<Option<X509>> =
LazyLock::new(|| parse_chain_certificate(R11));
pub fn get_lets_encrypt_chain_certificate(cn: &str) -> Option<X509> {
match cn.to_uppercase().as_str() {
"E5" => E5_CERTIFICATE.clone(),
"E6" => E6_CERTIFICATE.clone(),
"R10" => R10_CERTIFICATE.clone(),
"R11" => R11_CERTIFICATE.clone(),
_ => None,
}
}
#[cfg(test)]
mod tests {
use super::get_lets_encrypt_chain_certificate;
use pretty_assertions::assert_eq;
#[test]
fn test_get_lets_encrypt_chain_certificate() {
let e5 = get_lets_encrypt_chain_certificate("E5").unwrap();
assert_eq!(
r#"[countryName = "US", organizationName = "Let's Encrypt", commonName = "E5"]"#,
format!("{:?}", e5.subject_name())
);
assert_eq!("Mar 12 23:59:59 2027 GMT", e5.not_after().to_string());
let e6 = get_lets_encrypt_chain_certificate("E6").unwrap();
assert_eq!(
r#"[countryName = "US", organizationName = "Let's Encrypt", commonName = "E6"]"#,
format!("{:?}", e6.subject_name())
);
assert_eq!("Mar 12 23:59:59 2027 GMT", e6.not_after().to_string());
let r10 = get_lets_encrypt_chain_certificate("R10").unwrap();
assert_eq!(
r#"[countryName = "US", organizationName = "Let's Encrypt", commonName = "R10"]"#,
format!("{:?}", r10.subject_name())
);
assert_eq!("Mar 12 23:59:59 2027 GMT", r10.not_after().to_string());
let r11 = get_lets_encrypt_chain_certificate("R11").unwrap();
assert_eq!(
r#"[countryName = "US", organizationName = "Let's Encrypt", commonName = "R11"]"#,
format!("{:?}", r11.subject_name())
);
assert_eq!("Mar 12 23:59:59 2027 GMT", r11.not_after().to_string());
assert_eq!(true, get_lets_encrypt_chain_certificate("A").is_none());
}
}