-
Notifications
You must be signed in to change notification settings - Fork 10.3k
Add support for loading certificate chains from configuration. #24935
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -49,12 +49,13 @@ public SniOptionsSelector( | |
{ | ||
var sslOptions = new SslServerAuthenticationOptions | ||
{ | ||
ServerCertificate = certifcateConfigLoader.LoadCertificate(sniConfig.Certificate, $"{endpointName}:Sni:{name}"), | ||
EnabledSslProtocols = sniConfig.SslProtocols ?? fallbackHttpsOptions.SslProtocols, | ||
CertificateRevocationCheckMode = fallbackHttpsOptions.CheckCertificateRevocation ? X509RevocationMode.Online : X509RevocationMode.NoCheck, | ||
}; | ||
|
||
if (sslOptions.ServerCertificate is null) | ||
var (serverCert, intermediates) = certifcateConfigLoader.LoadCertificate(sniConfig.Certificate, $"{endpointName}:Sni:{name}"); | ||
|
||
if (serverCert is null) | ||
{ | ||
if (fallbackHttpsOptions.ServerCertificate is null && _fallbackServerCertificateSelector is null) | ||
{ | ||
|
@@ -63,21 +64,18 @@ public SniOptionsSelector( | |
|
||
if (_fallbackServerCertificateSelector is null) | ||
{ | ||
// Cache the fallback ServerCertificate since there's no fallback ServerCertificateSelector taking precedence. | ||
sslOptions.ServerCertificate = fallbackHttpsOptions.ServerCertificate; | ||
// Cache the fallback ServerCertificate since there's no fallback ServerCertificateSelector taking precedence. | ||
serverCert = fallbackHttpsOptions.ServerCertificate; | ||
intermediates = fallbackHttpsOptions.ServerCertificateIntermediates; | ||
} | ||
} | ||
|
||
if (sslOptions.ServerCertificate != null) | ||
if (serverCert != null) | ||
{ | ||
// This might be do blocking IO but it'll resolve the certificate chain up front before any connections are | ||
// made to the server | ||
sslOptions.ServerCertificateContext = SslStreamCertificateContext.Create((X509Certificate2)sslOptions.ServerCertificate, additionalCertificates: null); | ||
} | ||
|
||
if (!certifcateConfigLoader.IsTestMock && sslOptions.ServerCertificate is X509Certificate2 cert2) | ||
{ | ||
HttpsConnectionMiddleware.EnsureCertificateIsAllowedForServerAuth(cert2); | ||
sslOptions.ServerCertificate = serverCert; | ||
sslOptions.ServerCertificateContext = SslStreamCertificateContext.Create(serverCert, intermediates); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It might be more straightforward to just have developers call this themselves by putting a SslStreamCertificateContext on HttpsConnectionAdapterOptions and preferring it to ServerCertificate similar to the way we treat ServerCertificateSelector. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wherever we load the cert, we're going to be using the context. The callback happens to late. It needs to happen at startup. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. HttpsConnectionAdapterOptions.ServerCertificateContext or whatever-we-call-it would be set at startup though. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What does that have to do with the SNI selector? Kestrel should always resolve this at startup. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's just a comparison to point out that even though having both SslStreamCertificateContext and ServerCertificate on HttpsConnectionAdapterOptions would be redundant, ServerCertificateSelector and ServerCertificate are already redundant, so this isn't a new problem if we decide to add SslStreamCertificateContext. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't understand what this has to do with SNI. Exposing |
||
} | ||
|
||
var clientCertificateMode = sniConfig.ClientCertificateMode ?? fallbackHttpsOptions.ClientCertificateMode; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -751,18 +751,16 @@ private class MockCertificateConfigLoader : ICertificateConfigLoader | |
{ | ||
public Dictionary<object, string> CertToPathDictionary { get; } = new Dictionary<object, string>(ReferenceEqualityComparer.Instance); | ||
|
||
public bool IsTestMock => true; | ||
|
||
public X509Certificate2 LoadCertificate(CertificateConfig certInfo, string endpointName) | ||
public (X509Certificate2, X509Certificate2Collection) LoadCertificate(CertificateConfig certInfo, string endpointName) | ||
{ | ||
if (certInfo is null) | ||
{ | ||
return null; | ||
return (null, null); | ||
} | ||
|
||
var cert = TestResources.GetTestCertificate(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This gets called a lot. Maybe we should store this certificate in a static/fixture. We do that in some other test classes that need a lot of valid X509Certificate2s. |
||
CertToPathDictionary.Add(cert, certInfo.Path); | ||
return cert; | ||
return (cert, null); | ||
} | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The weird thing about this property is that it should really be set with the
ServerCertificate
in an atomic manner. If the cert is set, then the intermediates should be set as well (null is valid)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed. The combined type should probably be defined in the runtime.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we add a
SslStreamCertificateContext
property instead of thisX509Certificate2Collection
?