Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom TLS config #4032

Merged
merged 17 commits into from
Feb 27, 2025
Merged

Custom TLS config #4032

merged 17 commits into from
Feb 27, 2025

Conversation

aajtodd
Copy link
Contributor

@aajtodd aajtodd commented Feb 21, 2025

Motivation and Context

Description

Introduces a new TlsContext that can be used to customize TLS configuration. Currently that only includes supplying custom root certificates. This PR also refactors the way caching works. Previously we cached complete connectors with default resolver when the connector settings were known to be defaulted. The reason given in code and past commits for this caching resolves around the fact that hyper-rustls with_native_roots() configuration option re-loads platform root certificates on each invocation. Rather than cache the connector, instead I've switched the caching to only cache loading the certificates. This reduces a bit of complexity and required context to understand when we can cache.

Questions/Discussion

  1. There are a number of places we call unwrap/expect in this code. It was this way previously but I've introduced a few more. This stems from building a connector not returning a result. I don't know that I love this but I also suppose I can understand why we chose this. Now is the time to consider whether we'd approach it differently or not though or we are simply saying a valid HTTPS configuration.
  2. Loading native certs is all blocking file calls though and not async friendly. I haven't changed anything here but it caught my eye. It would be nice if this were more async friendly. The mitigation we chose to this seemed to be caching the connector and paying that cost once up front at construction time if possible.
  3. Both rustls and s2n take in PEM encoded certs. Rustls (via rustls-pki-types) provides a way to actually parse and load the certs as an independent configuration object (trust store). The issue is it converts them to DER format which makes using this for s2n not possible. It would be nice if we could load and validate certs before passing them off to rustls/s2n in a uniform way.
  4. Should TlsContext and/or TrustStore provider builders? Currently they just self mutate which is a pattern we use in some places (e.g. stalled stream protection config comes to mind).

Testing

New unit tests + existing TLS tests


By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

Copy link

A new generated diff is ready to view.

A new doc preview is ready to view.

Copy link

A new generated diff is ready to view.

A new doc preview is ready to view.

Copy link

A new generated diff is ready to view.

A new doc preview is ready to view.

Copy link

A new generated diff is ready to view.

A new doc preview is ready to view.

Copy link

A new generated diff is ready to view.

A new doc preview is ready to view.

@aajtodd aajtodd marked this pull request as ready for review February 25, 2025 20:55
@aajtodd aajtodd requested review from a team as code owners February 25, 2025 20:55
Copy link

A new generated diff is ready to view.

A new doc preview is ready to view.

}

/// Build a new [TlsContext]
pub fn build(self) -> Result<TlsContext, BoxError> {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Do we want a custom error type here?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah, we probably should.

Copy link

A new generated diff is ready to view.

A new doc preview is ready to view.

Copy link

A new generated diff is ready to view.

A new doc preview is ready to view.

Copy link

A new generated diff is ready to view.

A new doc preview is ready to view.

/// This may be called more than once to add multiple certificates.
/// NOTE: PEM certificate contents are not validated until passed to the configured
/// TLS provider.
pub fn with_pem_certificate(mut self, pem_bytes: &[u8]) -> Self {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Maybe impl AsRef<u8> or Into<Vec<u8>>?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Maybe we should have this and add_pem_certificate return a Result to allow for validation errors in the future to be pulled forward?

Copy link
Contributor

@landonxjames landonxjames Feb 26, 2025

Choose a reason for hiding this comment

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

Maybe we should have this and add_pem_certificate return a Result to allow for validation errors in the future to be pulled forward?

I think that is reasonable, and likely much easier to debug for a user than succeeding here and failing in rustls

Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe impl AsRef or Into<Vec>?

I probably prefer the latter since that's being honest about the function needing an owned value.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah it's only that way really because we have to store it until we convert it to either rustls or s2n configuration objects. I think if we were able to move to a common format and validate up front it maybe wouldn't be required to own it. Not 100% sure it will/would work out that way though.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think that is reasonable, and likely much easier to debug for a user than succeeding here and failing in rustls

Theres no way to move this forward (this being the possible validation errors). I'm going to leave it as is and if we ever have that capability we can at least validate in TlsContextBuilder::build() that the trust store configured is valid.

/// This may be called more than once to add multiple certificates.
/// NOTE: PEM certificate contents are not validated until passed to the configured
/// TLS provider.
pub fn with_pem_certificate(mut self, pem_bytes: &[u8]) -> Self {
Copy link
Contributor

@landonxjames landonxjames Feb 26, 2025

Choose a reason for hiding this comment

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

Maybe we should have this and add_pem_certificate return a Result to allow for validation errors in the future to be pulled forward?

I think that is reasonable, and likely much easier to debug for a user than succeeding here and failing in rustls

}

/// Build a new [TlsContext]
pub fn build(self) -> Result<TlsContext, BoxError> {
Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah, we probably should.

/// This may be called more than once to add multiple certificates.
/// NOTE: PEM certificate contents are not validated until passed to the configured
/// TLS provider.
pub fn with_pem_certificate(mut self, pem_bytes: &[u8]) -> Self {
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe impl AsRef or Into<Vec>?

I probably prefer the latter since that's being honest about the function needing an owned value.

Copy link

A new generated diff is ready to view.

A new doc preview is ready to view.

@aajtodd aajtodd merged commit 33b8247 into hyper1 Feb 27, 2025
42 of 45 checks passed
@aajtodd aajtodd deleted the hyper1-tls-context branch February 27, 2025 15:29
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.

3 participants