mz_ccsr/
tls.rs

1// Copyright Materialize, Inc. and contributors. All rights reserved.
2//
3// Use of this software is governed by the Business Source License
4// included in the LICENSE file.
5//
6// As of the Change Date specified in that file, in accordance with
7// the Business Source License, use of this software will be governed
8// by the Apache License, Version 2.0.
9
10//! TLS certificates and identities.
11
12use serde::{Deserialize, Serialize};
13
14use mz_tls_util::pkcs12der_from_pem;
15
16/// A [Serde][serde]-enabled wrapper around [`reqwest::Identity`].
17///
18/// [Serde]: serde
19#[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
20pub struct Identity {
21    der: Vec<u8>,
22    pass: String,
23}
24
25impl Identity {
26    /// Constructs an identity from a PEM-formatted key and certificate using OpenSSL.
27    pub fn from_pem(key: &[u8], cert: &[u8]) -> Result<Self, openssl::error::ErrorStack> {
28        let archive = pkcs12der_from_pem(key, cert)?;
29        Ok(Identity {
30            der: archive.der,
31            pass: archive.pass,
32        })
33    }
34
35    /// Wraps [`reqwest::Identity::from_pkcs12_der`].
36    pub fn from_pkcs12_der(der: Vec<u8>, pass: String) -> Result<Self, reqwest::Error> {
37        let _ = reqwest::Identity::from_pkcs12_der(&der, &pass)?;
38        Ok(Identity { der, pass })
39    }
40}
41
42impl From<Identity> for reqwest::Identity {
43    fn from(id: Identity) -> Self {
44        reqwest::Identity::from_pkcs12_der(&id.der, &id.pass).expect("known to be a valid identity")
45    }
46}
47
48/// A [Serde][serde]-enabled wrapper around [`reqwest::Certificate`].
49///
50/// [Serde]: serde
51#[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
52pub struct Certificate {
53    der: Vec<u8>,
54}
55
56impl Certificate {
57    /// Wraps [`reqwest::Certificate::from_pem`].
58    pub fn from_pem(pem: &[u8]) -> native_tls::Result<Certificate> {
59        Ok(Certificate {
60            der: native_tls::Certificate::from_pem(pem)?.to_der()?,
61        })
62    }
63
64    /// Wraps [`reqwest::Certificate::from_der`].
65    pub fn from_der(der: &[u8]) -> native_tls::Result<Certificate> {
66        let _ = native_tls::Certificate::from_der(der)?;
67        Ok(Certificate { der: der.into() })
68    }
69}
70
71impl From<Certificate> for reqwest::Certificate {
72    fn from(cert: Certificate) -> Self {
73        reqwest::Certificate::from_der(&cert.der).expect("known to be a valid cert")
74    }
75}