rustls_acme/caches/
test.rs

1use crate::{AccountCache, CertCache};
2use async_trait::async_trait;
3use rcgen::{date_time_ymd, BasicConstraints, CertificateParams, DistinguishedName, DnType, IsCa, KeyPair, KeyUsagePurpose, PKCS_ECDSA_P256_SHA256};
4use std::fmt::Debug;
5use std::marker::PhantomData;
6use std::sync::atomic::AtomicPtr;
7use std::sync::Arc;
8
9/// Test cache, which generates certificates for ACME incompatible test environments.
10/// ```rust
11/// # use rustls_acme::{AcmeConfig};
12/// # use rustls_acme::caches::{DirCache, TestCache};
13/// # let test_environment = true;
14/// let mut config = AcmeConfig::new(["example.com"])
15///     .cache(DirCache::new("./cache"));
16/// if test_environment {
17///     config = config.cache(TestCache::default());
18/// }
19/// ```
20#[derive(Clone)]
21pub struct TestCache<EC: Debug = std::io::Error, EA: Debug = std::io::Error> {
22    ca_key: Arc<KeyPair>,
23    ca_cert: Arc<rcgen::Certificate>,
24    ca_pem: Arc<String>,
25    _cert_error: PhantomData<AtomicPtr<Box<EC>>>,
26    _account_error: PhantomData<AtomicPtr<Box<EA>>>,
27}
28
29impl<EC: Debug, EA: Debug> Default for TestCache<EC, EA> {
30    fn default() -> Self {
31        let mut params = CertificateParams::default();
32        let mut distinguished_name = DistinguishedName::new();
33        distinguished_name.push(DnType::CountryName, "US");
34        distinguished_name.push(DnType::OrganizationName, "Test CA");
35        distinguished_name.push(DnType::CommonName, "Test CA");
36        params.distinguished_name = distinguished_name;
37        params.is_ca = IsCa::Ca(BasicConstraints::Unconstrained);
38        params.key_usages = vec![KeyUsagePurpose::KeyCertSign, KeyUsagePurpose::CrlSign];
39        params.not_before = date_time_ymd(2000, 1, 1);
40        params.not_after = date_time_ymd(3000, 1, 1);
41        let key_pair = KeyPair::generate_for(&PKCS_ECDSA_P256_SHA256).unwrap();
42        let ca_cert = params.self_signed(&key_pair).unwrap();
43        let ca_pem = ca_cert.pem();
44        Self {
45            ca_key: key_pair.into(),
46            ca_cert: ca_cert.into(),
47            ca_pem: ca_pem.into(),
48            _cert_error: Default::default(),
49            _account_error: Default::default(),
50        }
51    }
52}
53
54impl<EC: Debug, EA: Debug> TestCache<EC, EA> {
55    pub fn ca_pem(&self) -> &str {
56        &self.ca_pem
57    }
58}
59
60#[async_trait]
61impl<EC: Debug, EA: Debug> CertCache for TestCache<EC, EA> {
62    type EC = EC;
63    async fn load_cert(&self, domains: &[String], _directory_url: &str) -> Result<Option<Vec<u8>>, Self::EC> {
64        let mut params = CertificateParams::new(domains).unwrap();
65        let mut distinguished_name = DistinguishedName::new();
66        distinguished_name.push(DnType::CommonName, "Test Cert");
67        params.distinguished_name = distinguished_name;
68        params.not_before = date_time_ymd(2000, 1, 1);
69        params.not_after = date_time_ymd(3000, 1, 1);
70        let key_pair = KeyPair::generate_for(&PKCS_ECDSA_P256_SHA256).unwrap();
71        let cert = params.signed_by(&key_pair, &self.ca_cert, &self.ca_key).unwrap();
72        let private_key_pem = key_pair.serialize_pem();
73        let signed_cert_pem = cert.pem();
74        Ok(Some([&private_key_pem, "\n", &signed_cert_pem, "\n", &self.ca_pem].concat().into_bytes()))
75    }
76    async fn store_cert(&self, _domains: &[String], _directory_url: &str, _cert: &[u8]) -> Result<(), Self::EC> {
77        log::info!("test cache configured, could not store certificate");
78        Ok(())
79    }
80}
81
82#[async_trait]
83impl<EC: Debug, EA: Debug> AccountCache for TestCache<EC, EA> {
84    type EA = EA;
85    async fn load_account(&self, _contact: &[String], _directory_url: &str) -> Result<Option<Vec<u8>>, Self::EA> {
86        log::info!("test cache configured, could not load account");
87        Ok(None)
88    }
89    async fn store_account(&self, _contact: &[String], _directory_url: &str, _account: &[u8]) -> Result<(), Self::EA> {
90        log::info!("test cache configured, could not store account");
91        Ok(())
92    }
93}