trz_gateway_common/security_configuration/certificate/
pem.rs

1use std::sync::Arc;
2
3use nameth::NamedEnumValues as _;
4use nameth::nameth;
5use openssl::error::ErrorStack;
6use openssl::pkey::PKey;
7use openssl::x509::X509;
8
9use super::CertificateConfig;
10use super::X509CertificateInfo;
11use crate::certificate_info::CertificateInfo;
12use crate::security_configuration::common::parse_pem_certificates;
13
14/// A [CertificateConfig] based on PEM files stored on disk.
15#[nameth]
16#[derive(Clone, Default, PartialEq, Eq)]
17pub struct PemCertificate {
18    pub intermediates_pem: String,
19    pub certificate_pem: String,
20    pub private_key_pem: String,
21}
22
23impl CertificateConfig for PemCertificate {
24    type Error = PemCertificateError;
25
26    fn certificate(&self) -> Result<Arc<X509CertificateInfo>, Self::Error> {
27        let certificate = X509::from_pem(self.certificate_pem.as_bytes())
28            .map_err(PemCertificateError::InvalidLeafPemCertificate)?;
29        let private_key = PKey::private_key_from_pem(self.private_key_pem.as_bytes())
30            .map_err(PemCertificateError::InvalidPemPrivateKey)?;
31        Ok(X509CertificateInfo {
32            certificate,
33            private_key,
34        }
35        .into())
36    }
37
38    fn intermediates(&self) -> Result<Arc<Vec<X509>>, Self::Error> {
39        let mut intermediates = vec![];
40        for intermediate in parse_pem_certificates(&self.intermediates_pem) {
41            let intermediate =
42                intermediate.map_err(PemCertificateError::InvalidIntermediatePemCertificate)?;
43            intermediates.push(intermediate);
44        }
45        Ok(intermediates.into())
46    }
47}
48
49#[nameth]
50#[derive(thiserror::Error, Debug)]
51pub enum PemCertificateError {
52    #[error("[{n}] Invalid leaf PEM certificate: {0}", n = self.name())]
53    InvalidLeafPemCertificate(ErrorStack),
54
55    #[error("[{n}] Invalid intermediate PEM certificate: {0}", n = self.name())]
56    InvalidIntermediatePemCertificate(ErrorStack),
57
58    #[error("[{n}] Invalid X509 certificate: {0}", n = self.name())]
59    InvalidPemPrivateKey(ErrorStack),
60}
61
62/// Convert a [CertificateInfo] (aka cert+key) into a [PemCertificate].
63///
64/// The resulting [PemCertificate] won't have any intermediates.
65impl From<CertificateInfo<String>> for PemCertificate {
66    fn from(value: CertificateInfo<String>) -> Self {
67        Self {
68            intermediates_pem: String::default(),
69            certificate_pem: value.certificate,
70            private_key_pem: value.private_key,
71        }
72    }
73}
74
75mod debug {
76    use std::fmt::Debug;
77    use std::fmt::Formatter;
78
79    use nameth::NamedType as _;
80
81    use super::PemCertificate;
82
83    impl Debug for PemCertificate {
84        fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
85            f.debug_struct(PemCertificate::type_name()).finish()
86        }
87    }
88}