tokio_rustls_acme2/caches/
test.rs

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