pavex/tls/client/
config.rs

1//! Configure the TLS policy for a client.
2//!
3//! Check out the documentation for [`TlsClientPolicyConfig`](super::TlsClientPolicyConfig) for
4//! a detailed explanation of the available configuration options.
5use serde::{Deserialize, Serialize};
6use std::path::PathBuf;
7
8// Wrapped into a sub-module to avoid exposing `TlsClientPolicyConfig` in two places:
9// inside `pavex::tls::config` and `pavex::tls::client`.
10// We only want users to see `pavex::tls::client::TlsClientPolicyConfig`.
11pub(crate) mod _config {
12    use super::*;
13
14    /// Configure the TLS policy for a client.
15    ///
16    /// It covers:
17    /// - The [cryptographic stack](`Self::crypto_provider`) used to secure the connection.
18    /// - Which [TLS versions](`Self::allowed_versions`) are allowed.
19    /// - The [certificate verification](`Self::certificate_verification`) mechanism used to verify server certificates.
20    ///
21    /// For testing/development purposes only, it exposes a few [insecure](`Self::insecure`) configuration options
22    /// that lower the security posture of your client.
23    ///
24    /// # Defaults
25    ///
26    /// The default configuration should be suitable for most production environments:
27    ///
28    /// ```yaml
29    #[doc = include_str!("../../../tests/fixtures/tls_config/default.yaml")]
30    /// ```
31    ///
32    /// # Overriding the default configuration
33    ///
34    /// If you want to deviate from the default configuration, it's enough to specify the fields you
35    /// want to override.
36    ///
37    /// ## Example: Disable TLS 1.2
38    ///
39    /// ```yaml
40    #[doc = include_str!("../../../tests/fixtures/tls_config/disable_tls_1_2.yaml")]
41    /// ```
42    ///
43    /// ## Example: Trust additional root certificates
44    ///
45    /// ```yaml
46    #[doc = include_str!("../../../tests/fixtures/tls_config/additional_roots.yaml")]
47    /// ```
48    ///
49    /// ## Example: Disable certificate verification
50    ///
51    /// ```yaml
52    #[doc = include_str!("../../../tests/fixtures/tls_config/skip_verification.yaml")]
53    /// ```
54    #[derive(Debug, Default, Clone, Deserialize, Serialize)]
55    #[non_exhaustive]
56    pub struct TlsClientPolicyConfig {
57        /// The cryptographic stack used to secure the connection.
58        ///
59        /// Refer to the documentation for [`CryptoProviderConfig`]
60        /// for more details.
61        #[serde(default)]
62        #[serde(with = "serde_yaml::with::singleton_map_recursive")]
63        pub crypto_provider: CryptoProviderConfig,
64        /// Which TLS versions are allowed.
65        ///
66        /// Refer to the documentation for [`AllowedTlsVersionsConfig`]
67        /// for more details.
68        #[serde(default)]
69        pub allowed_versions: AllowedTlsVersionsConfig,
70        /// The mechanism used to verify server certificates.
71        ///
72        /// Refer to the documentation for [`CertificateVerificationConfig`]
73        /// for more details.
74        #[serde(default)]
75        pub certificate_verification: CertificateVerificationConfig,
76        /// Dangerous configuration options that lower the security
77        /// posture of your client.
78        ///
79        /// These options should never be used in production scenarios.
80        /// They are available for testing/development purposes only.
81        #[serde(default)]
82        pub insecure: InsecureTlsClientConfig,
83    }
84}
85
86/// Which TLS versions are allowed.
87///
88/// By default, TLS 1.2 and TLS 1.3 are enabled.
89///
90/// # Security
91///
92/// The lack of support for TLS 1.0 and TLS 1.1 is intentional.
93#[derive(Debug, Clone, Copy, Deserialize, Serialize)]
94#[non_exhaustive]
95pub struct AllowedTlsVersionsConfig {
96    /// Enables TLS 1.2 if `true`.
97    ///
98    /// It requires the server to support TLS 1.2.
99    #[serde(default = "default_v1_2")]
100    pub v1_2: bool,
101    /// Enables TLS 1.3 if `true`.
102    ///
103    /// It requires the server to support TLS 1.3.
104    #[serde(default = "default_v1_3")]
105    pub v1_3: bool,
106}
107
108fn default_v1_2() -> bool {
109    true
110}
111
112fn default_v1_3() -> bool {
113    true
114}
115
116impl Default for AllowedTlsVersionsConfig {
117    fn default() -> Self {
118        Self {
119            v1_2: default_v1_2(),
120            v1_3: default_v1_3(),
121        }
122    }
123}
124
125/// Configure how server certificates are verified.
126///
127/// # Default
128///
129/// By default, we rely on verification machinery of the underlying operating system.
130/// Refer to the documentation for [`rustls-platform-verifier`](https://docs.rs/rustls-platform-verifier/latest/rustls_platform_verifier/)
131/// for more information on how each platform handles certificate verification.
132///
133/// # Customization
134///
135/// Set [`additional_roots`][`CertificateVerificationConfig::additional_roots`] to trust
136/// additional root certificates in addition to the ones already trusted
137/// by the operating system.
138///
139/// # Skipping Verification
140///
141/// If you want to skip certificate verification altogether, check out the [`insecure`][`super::TlsClientPolicyConfig::insecure`]
142/// options in [`TlsClientPolicyConfig`][`super::TlsClientPolicyConfig`].
143///
144/// ## Incorrect Usage
145///
146/// Setting [`use_os_verifier`][`CertificateVerificationConfig::use_os_verifier`] to `false`, with
147/// no [`additional_roots`][`CertificateVerificationConfig::additional_roots`] specified, does **not**
148/// disable certificate verification. It does instead cause all certificate verification attempts to fail.
149///
150/// We treat this scenario as a misconfiguration and return an error at runtime, when
151/// trying to initialize the client.
152#[derive(Debug, Clone, Deserialize, Serialize)]
153#[non_exhaustive]
154pub struct CertificateVerificationConfig {
155    /// Whether to use the certificate verification machinery provided by
156    /// the underlying operating system.
157    ///
158    /// Defaults to `true`.
159    #[serde(default = "default_use_os_verifier")]
160    pub use_os_verifier: bool,
161    /// Trust one or more additional root certificates.
162    ///
163    /// If [`use_os_verifier`][`CertificateVerificationConfig::use_os_verifier`] is `false`,
164    /// these will be the only trusted root certificates.
165    /// If [`use_os_verifier`][`CertificateVerificationConfig::use_os_verifier`] is `true`, these will be
166    /// trusted **in addition** to the ones already trusted by the underlying operating system.
167    ///
168    /// They can either be loaded from files or inlined in configuration.
169    #[serde(default)]
170    #[serde(with = "serde_yaml::with::singleton_map_recursive")]
171    pub additional_roots: Vec<RootCertificate>,
172}
173
174fn default_use_os_verifier() -> bool {
175    true
176}
177
178impl Default for CertificateVerificationConfig {
179    fn default() -> Self {
180        CertificateVerificationConfig {
181            use_os_verifier: default_use_os_verifier(),
182            additional_roots: Default::default(),
183        }
184    }
185}
186
187/// [Additional root certificates](`CertificateVerificationConfig::additional_roots`) to be trusted.
188#[derive(Debug, Clone, Deserialize, Serialize)]
189#[serde(rename_all = "snake_case")]
190#[non_exhaustive]
191pub enum RootCertificate {
192    /// Retrieve the root certificate from a file.
193    File {
194        /// How to decode the root certificate inside the file.
195        encoding: RootCertificateFileEncoding,
196        /// The path to the root certificate file.
197        path: PathBuf,
198    },
199    /// A root certificate inlined inside the provided configuration.
200    Inline {
201        /// A PEM-encoded X.509 certificate; as specified in [RFC 7468](https://datatracker.ietf.org/doc/html/rfc7468#section-5).
202        data: String,
203    },
204}
205
206/// Supported encodings for the root certificate in [`RootCertificate::File`].
207#[derive(Debug, Clone, Deserialize, Serialize)]
208#[serde(rename_all = "snake_case")]
209#[non_exhaustive]
210pub enum RootCertificateFileEncoding {
211    /// A DER-encoded X.509 certificate; as specified in [RFC 5280](https://datatracker.ietf.org/doc/html/rfc5280#section-4.1).
212    Der,
213    /// A PEM-encoded X.509 certificate; as specified in [RFC 7468](https://datatracker.ietf.org/doc/html/rfc7468#section-5).
214    Pem,
215}
216
217/// Dangerous configuration options to lower the security posture of a TLS client.
218#[derive(Debug, Clone, Deserialize, Serialize)]
219#[non_exhaustive]
220pub struct InsecureTlsClientConfig {
221    /// Don't verify server certificates.
222    ///
223    /// Extremely dangerous option, limit its usage to local development environments.
224    #[serde(default = "default_skip_verification")]
225    pub skip_verification: bool,
226}
227
228impl Default for InsecureTlsClientConfig {
229    fn default() -> Self {
230        InsecureTlsClientConfig {
231            skip_verification: default_skip_verification(),
232        }
233    }
234}
235
236fn default_skip_verification() -> bool {
237    false
238}
239
240/// Which implementation to use for TLS cryptographic operations.
241#[derive(Debug, Default, Copy, Clone, Deserialize, Serialize)]
242#[serde(rename_all = "snake_case")]
243#[non_exhaustive]
244pub enum CryptoProviderConfig {
245    /// Use [`aws-lc-rs`](https://docs.rs/aws-lc-rs/) for cryptographic operations.
246    ///
247    /// If you require FIPS compliance, use the [`AwsLcRsFips`][`CryptoProviderConfig::AwsLcRsFips`]
248    /// instead.
249    #[default]
250    AwsLcRs,
251    /// Use [`aws-lc-rs`](https://docs.rs/aws-lc-rs/) for cryptographic operations,
252    /// in FIPS-compliant mode.
253    ///
254    /// # Additional constraints
255    ///
256    /// FIPS mode is not supported on all platforms.
257    /// Furthermore, `aws-lc-rs` requires additional system dependencies at build time.
258    /// Check out their [documentation](https://docs.rs/aws-lc-rs/latest/aws_lc_rs/#fips) for
259    /// more information.
260    AwsLcRsFips,
261    /// Use [`ring`](https://docs.rs/ring/) for cryptographic operations.
262    Ring,
263}