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

Configuration of client certificate options #100

Closed
ghost opened this issue May 26, 2020 · 8 comments · Fixed by #109
Closed

Configuration of client certificate options #100

ghost opened this issue May 26, 2020 · 8 comments · Fixed by #109
Assignees
Labels
enhancement New feature or request
Milestone

Comments

@ghost
Copy link

ghost commented May 26, 2020

Is your feature request related to a problem? Please describe.
Kestrel does not seem to provide a configuration file-based approach for setting the defaults for HTTPS endpoints. As such, the recommended approach is to call ConfigureKestrel then ConfigureHttpsDefaults to enable client certificate support. However, this seems to override the KestrelOptionsSetup class that is registered by LettuceEncrypt. As such, automatic certificate selection and TLS ALPN challenges are not supported when client certificates are enabled.

There does not appear to be a way to chain multiple calls to ConfigureHttpsDefaults, as it's stored in a single HttpsDefaults property on KestrelServerOptions. Only the last Action provided to ConfigureHttpsDefaults will be used, the others are silently ignored.

There is also no way to manually invoke the LettuceEncrypt options afterwards, as the three classes involved are internal (KestrelOptionsSetup, TlsAlpnChallengeResponder & CertificateSelector),

Describe the solution you'd like
Possible solutions include:

  • A way to register another Action or class to be called from KestrelOptionsSetup after LettuceEncrypt has configured its own settings, eg:
services.AddLetsEncrypt(o => {
  o.ConfigureHttpsDefaults(h => {
    h.ClientCertificateMode = ClientCertificateMode.RequireCertificate;
    h.ClientCertificateValidation = MyValidationMethod;
  }
});
  • A public extension method in LettuceEncrypt linked to HttpsConnectionAdapterOptions that can manually be called to configure LettuceEncrypt if ConfigureHttpsDefaults needs to be invoked from the calling application, eg:
public void Configure(KestrelServerOptions options) {
  options.ConfigureHttpsDefaults(o => {
    o.ClientCertificateMode = ClientCertificateMode.RequireCertificate;
    o.ClientCertificateValidation = MyValidationMethod;
    o.AddLettuceEncrypt();
  }
}

Describe alternatives you've considered

  1. We can use code to enable client certificates then manually specify the SSL server certificate to use in appsettings.json. This does not invoke KestrelOptionsSetup, so does not support TLS ALPN challenges, and requires a lot of configuration (eg: domain names need to be listed in multiple places in the JSON file for both Kestrel & LettuceEncrypt to use).

  2. IConfigureOptions<T> is not used for HttpsConnectionAdapterOptions by Kestrel, which prevents that pattern from being used to register multiple providers to configure those options. However, I've created a hacky workaround by registering a class that implements IConfigureOptions<KestrelServerOptions>. It uses reflection to get the previous value of the HttpsDefaults private property on KestrelServerOptions so that we can call ConfigureHttpsDefaults, invoke the previous callback then set the new properties that we want. However, this is a fragile workaround as it is dependent on private APIs.

@ghost ghost added the enhancement New feature or request label May 26, 2020
@natemcmaster natemcmaster added the help wanted I would accept a PR to help complete this issue label May 30, 2020
@natemcmaster natemcmaster removed the help wanted I would accept a PR to help complete this issue label May 31, 2020
@natemcmaster natemcmaster added this to the 1.1.0 milestone May 31, 2020
@natemcmaster natemcmaster self-assigned this May 31, 2020
@natemcmaster
Copy link
Owner

@carey-bishop I couldn't find a way to fix this without requiring new API and you to add additional configuration to your code. I've opened a PR to implement the second option you described, #109. Usage would look like this:

webBuilder.UseKestrel(k =>
{
var appServices = k.ApplicationServices;
k.ConfigureHttpsDefaults(h =>
{
h.ClientCertificateMode = ClientCertificateMode.RequireCertificate;
h.UseLettuceEncrypt(appServices);
});
});

Would appreciate feedback.

At the same time, it might be nice to ask the aspnetcore team to make this easier to do with dependency injection. If that becomes an option in .NET 5 or later, we could update this library to take advantage of that.

@Tratcher
Copy link
Contributor

Tratcher commented Jun 1, 2020

At the same time, it might be nice to ask the aspnetcore team to make this easier to do with dependency injection

Like making HttpsDefaults into a list of callbacks so you could call ConfigureHttpsDefaults multiple times for cumulative effect?

@natemcmaster
Copy link
Owner

That, or IOptions<HttpsConnectionAdapterOptions> so you can use your regular IConfigureOptions and IPostConfigureOptions interfaces to build up a cumulative effect.

@natemcmaster
Copy link
Owner

PR auto-closed. Re-opening until this is released with 1.1.0. Still open to feedback.

@natemcmaster natemcmaster reopened this Jun 1, 2020
@AraHaan

This comment has been minimized.

@natemcmaster

This comment has been minimized.

@ghost
Copy link
Author

ghost commented Jun 2, 2020

Thanks @natemcmaster, the new API seems to work well.

As you mention, use of the IOptions<HttpsConnectionAdapterOptions> pattern in Kestrel would be a much nicer approach, but this works just fine.

@natemcmaster
Copy link
Owner

I'm going to release 1.1.0 today. Thanks for your patience with this project.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants