Skip to content

feat: Add client TLS configuration, with built-in support for rustls - #547

Merged
LukeMathWalker merged 3 commits into
mainfrom
client-tls-config
Oct 4, 2025
Merged

LukeMathWalker merged 3 commits into
mainfrom
client-tls-config

Conversation

@LukeMathWalker

Copy link
Copy Markdown
Owner

No description provided.

@LukeMathWalker

Copy link
Copy Markdown
Owner Author

/ok-to-test sha=6a30581

@LukeMathWalker

Copy link
Copy Markdown
Owner Author

/ok-to-test sha=161ebc0

@djc djc left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here's some (fairly opinionated) feedback. This seems very much designed from the inside out (that is, what does the rustls API support) rather than outside in (what do users actually need), and as a result it feels overengineered to me.

Comment thread libs/Cargo.toml Outdated
reqwest-retry = "0.7.0"
reqwest-tracing = "0.5.8"
rustls = "0.23"
rustls-pki-types = "1.12.0"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pki-types is re-exported via rustls as rustls::pki_types, so you could probably skip the separate dependency.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TIL, thanks!

Comment thread libs/pavex/src/tls/client/config.rs Outdated
/// # Security
///
/// The lack of support for TLS 1.0 and TLS 1.1 is intentional.
pub struct AllowedTlsVersionsConfig {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you have an actual use case for this today? If not, I'd skip it -- can always add it later and there's a fairly obvious default.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've pushed more than a few TLS1.3-only deployments, hence the inclusion!

#[serde(rename_all = "snake_case")]
#[non_exhaustive]
/// Supported encodings for the root certificate in [`RootCertificate::File`].
pub enum RootCertificateFileEncoding {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you have an actual use case for DER-encoded files? PEM is widespread and it seems like over-engineering to support both.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I am aware, DER is still pretty common in the Windows ecosystem and adjacent universes (e.g. .NET).

Comment thread libs/pavex/src/tls/client/config.rs Outdated
/// A DER-encoded X.509 certificate; as specified in [RFC 5280](https://datatracker.ietf.org/doc/html/rfc5280#section-4.1).
///
/// Since DER is a binary format, we expect the data to be [base64-encoded](https://datatracker.ietf.org/doc/html/rfc4648#section-4).
Base64Der,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the value of supporting a non-standard base64 DER in YAML encoding? PEM is pretty much base64 DER anyway, and is widely supported. Seems like YAGNI.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thinking about it again, you're 100% right.

#[serde(rename_all = "kebab-case", tag = "name")]
#[non_exhaustive]
/// Which implementation to use for TLS cryptographic operations.
pub enum CryptoProviderConfig {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems strange to me to provide run-time configuration support for crypto stacks since it's mostly a compile-time constraint. Even if you did want to do this, I'd suggest just simplifying to having separate variants for aws-lc-rs and aws-lc-rs-fips.

@LukeMathWalker LukeMathWalker Oct 2, 2025 •

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I strongly dislike the use of compile-time features to control default choices (or to make choices at all).
I prefer to use features to control the availability of a certain piece of functionality while using runtime configuration to decide which of that functionality should be used.

fn parse_certificates_from_pem_bytes(data: &[u8]) -> Result<Vec<CertificateDer<'static>>> {
let mut certs = Vec::new();
for outcome in
<(SectionKind, Vec<u8>) as rustls_pki_types::pem::PemObject>::pem_slice_iter(data)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not <CertificateDer as _>::pem_slice_iter()?

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Different behaviour if a certificate of a different kind is encountered—I prefer to be strict and fail if the bundle contains other certificate kinds (e.g. a private key) rather than ignoring it.

@LukeMathWalker

Copy link
Copy Markdown
Owner Author

First of all, thanks for having a look!

This seems very much designed from the inside out (that is, what does the rustls API support) rather than outside in (what do users actually need), and as a result it feels overengineered to me.

It's interesting you say that, because the design journey started rather far from rustls!
My primary source of inspiration was Caddy's configuration for reverse proxies, which I then aggressively stripped down to the options I actually found myself using in production projects over the years. The crypto-provider bit is the only rustls-specific bit included (and a simplified version of trust_pool as certification_verification since rustls-platform-verifier is around now).

@LukeMathWalker
LukeMathWalker force-pushed the client-tls-config branch 7 times, most recently from 4411579 to 4b8f5ed Compare October 3, 2025 13:56
@LukeMathWalker
LukeMathWalker merged commit 36351c8 into main Oct 4, 2025
32 of 33 checks passed
@LukeMathWalker
LukeMathWalker deleted the client-tls-config branch October 4, 2025 09:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants