trz_gateway_common/security_configuration/certificate/
as_trusted_store.rs

1use std::convert::Infallible;
2use std::sync::Arc;
3
4use nameth::NamedEnumValues as _;
5use nameth::nameth;
6use openssl::error::ErrorStack;
7use openssl::x509::store::X509Store;
8use openssl::x509::store::X509StoreBuilder;
9
10use super::CertificateConfig;
11use super::cache::CachedCertificate;
12use super::pem::PemCertificate;
13use super::pem::PemCertificateError;
14use crate::security_configuration::trusted_store::TrustedStoreConfig;
15
16/// [PemCertificate] is both
17///   - primarily a certificate+intermediates, that is [CertificateConfig],
18///   - can also be used as a root CA [TrustedStoreConfig].
19///
20/// In the latter case, the list of intermediates is empty,
21/// the [PemCertificate] represents a single self-signed CA.
22impl TrustedStoreConfig for PemCertificate {
23    type Error = AsTrustedStoreError<PemCertificateError>;
24    fn root_certificates(&self) -> Result<Arc<X509Store>, Self::Error> {
25        as_trusted_store(self)
26    }
27}
28
29impl TrustedStoreConfig for CachedCertificate {
30    type Error = AsTrustedStoreError<Infallible>;
31
32    fn root_certificates(&self) -> Result<Arc<X509Store>, Self::Error> {
33        as_trusted_store(self)
34    }
35}
36
37pub fn as_trusted_store<C: CertificateConfig>(
38    certificate: &C,
39) -> Result<Arc<X509Store>, AsTrustedStoreError<C::Error>> {
40    let mut trusted_roots =
41        X509StoreBuilder::new().map_err(AsTrustedStoreError::X509StoreBuilder)?;
42    trusted_roots
43        .add_cert(
44            certificate
45                .certificate()
46                .map_err(AsTrustedStoreError::Certificate)?
47                .certificate
48                .clone(),
49        )
50        .map_err(AsTrustedStoreError::AddCert)?;
51    Ok(Arc::new(trusted_roots.build()))
52}
53
54#[nameth]
55#[derive(thiserror::Error, Debug)]
56pub enum AsTrustedStoreError<E: std::error::Error> {
57    #[error("[{n}] Failed to create X509StoreBuilder: {0}", n = self.name())]
58    X509StoreBuilder(ErrorStack),
59
60    /// The [CertificateConfig] failed to generate an [openssl::x509::X509].
61    #[error("[{n}] {0}", n = self.name())]
62    Certificate(E),
63
64    #[error("[{n}] Failed to add a X509 certificate to the store: {0}", n = self.name())]
65    AddCert(ErrorStack),
66}