Repository navigation
Kestrel support for an asynchronous server certificate selector. #6968
Description
Activity
Are you hitting key vault per connection?
This proposal would enable the host to retrieve the desired certificate from key vault as often or as little as needed. Accessing key vault for every connection is one end of the spectrum for a service that does not want its certificate(s) to be persisted on the host machine. Accessing key vault only when the certificate is missing or expired is the other end of the spectrum for a service that would like to be resilient against the common problem of certificate expiration/rotation.
Why not do it on startup then? Not saying it isn't useful to make this callback async (or add an async version) but I'd like to understand how it would be used. The other pattern for something like this is to trigger an update in the background and replace the old value with the new one once it's ready.
This would enable the Let's Encrypt scenario as well 👍
@davidfowl
Could the server certificate be retrieved asynchronously from secure storage during startup? Yes. However, rotating an expired certificate would then require a service restart.Could the certificate be updated in a background task or hosted service that replaces the old value with a new value when available? Yes. Since the server certificate selector runs synchronously, that is most likely how existing services are handling certificate expiration and rotation.
Enabling the server certificate selector to run asynchronously would provide developers with another alternative approach to automate certificate rotation without needing to restart the service. Check out this example to get an idea of how an asynchronous server certificate selector could be used.
@davidfowl
On further inspection, it seems that this request would require changes in .NET. The synchronous nature of the server certificate selector is enforced by the definition of the ServerCertificateSelectionCallback delegate.We'll revisit when/if SslStream adds this support.
- addedaffected-fewThis issue impacts only small number of customersThis issue impacts only small number of customersenhancementThis issue represents an ask for new feature or an enhancement to an existing oneThis issue represents an ask for new feature or an enhancement to an existing oneseverity-minorThis label is used by an internal toolThis label is used by an internal tool
on Nov 12, 2020 Closing as this as we implemented this feature through calling
UseHttpswith a server option selection callback:public static ListenOptions UseHttps(this ListenOptions listenOptions, ServerOptionsSelectionCallback serverOptionsSelectionCallback, object state) - ghost locked as resolved and limited conversation to collaborators
on Dec 13, 2020 - addedarea-networkingIncludes servers, yarp, json patch, bedrock, websockets, http client factory, and http abstractionsIncludes servers, yarp, json patch, bedrock, websockets, http client factory, and http abstractionsand removed
on Jun 2, 2023
What is the problem?
The HttpsConnectionAdapterOptions class provides a callback to dynamically select a server certificate that runs synchronously. This fails to accommodate callback implementations that wish to retrieve certificates asynchronously from secure storage (e.g. Azure Key Vault).
What is the proposed solution?
This can be solved by updating the HttpsConnectionAdapterOptions class to provide an asynchronous callback property that retrieves the desired certificate. For example:
Func<ConnectionContext, string, Task<X509Certificate2>> ServerCertificateSelector { get; set; }This can be designed as a breaking change by updating the existing ServerCertificateSelector property, or as a non-breaking change by adding a new property (e.g. ServerCertificateAsyncSelector) that supersedes both the ServerCertificate and ServerCertificateSelector properties when it is specified.
I'd be happy to submit a PR for this once a design is agreed upon.