Kestrel inconsistent certificate chain handling between endpoint and default configuration #60709
Closed
1 task done
Labels
area-networking
Includes servers, yarp, json patch, bedrock, websockets, http client factory, and http abstractions
Milestone
Is there an existing issue for this?
Describe the bug
On Kestrel server, there is inconsistent behavior configuring certificates per endpoint versus in the “Default” configuration. The discrepancy occurs when specifying a certificate file containing a chain of certificates where the chain is not included in the system's trust store.
I tested this on Windows, Mac, and Ubuntu using certificate files of the form:
The files were generated using step CLI, and none of the root or intermediate certificates were in the system trust store initially. For each of the following, I removed the certificates from the trust store before each test.
On Windows:
If a certificate file is specified in an endpoint's configuration section, Kestrel will:
openssl s_client -connect localhost:5000 -showcerts
andopenssl s_client -connect localhost:5001 -showcerts
correctly responds with a full certificate chain as specified inserver_certificate.crt
.The intermediate will also be added to the Windows Certificate Store if it is not present.
If the certificate file is specified only in the default configuration section:
openssl s_client -connect localhost:5000 -showcerts
only responds with the leaf certificate specified inserver_certificate.crt
, and the intermediate is not added to the certificate store.On MacOS:
If a certificate file is specified in an endpoint's configuration section, Kestrel will:
If the certificate file is specified in the default configuration section:
openssl s_client -connect localhost:5001 -showcerts
will only present us the leaf certificate.Behavior on Ubuntu:
Relevant Code Snippet
This behavior appears to be caused by this line in
TlsConfigurationLoader.cs
:which does not process the full certificate chain when it is used in the default configuration section. As a result, the subsequent call to
SslStreamCertificateContext.Create
does not add the full certificate chain:On Mac and Ubuntu this means the chain is never presented on endpoints using the default configuration.
On Windows,
SslStreamCertificateContext.Create
adds intermediates specified in the call to the Windows Certificate Store if they are not already present. This means if the certificate chain has been specified on an endpoint level configuration, it will be added to the Windows trust store, and subsequently any endpoints specified using the default configuration will also have their full chain presented.However, if the file is only specified on the default configuration, the chain will be thrown out and never added to the trust store from this call, so any endpoints using the default configuration will only present their leaf certificates.
Expected Behavior
The behavior when specifying the certificate file in an individual endpoint’s configuration should have identical behavior to endpoints using the default configuration. The full certificate chain should be included for endpoints using the default configuration when possible.
Steps To Reproduce
step
CLI or similar CA such as Hashicorp Vault, where intermediates are not in the system trust storeopenssl s_client -connect localhost:5000 -showcerts
, and observe the certificate chainExceptions (if any)
No response
.NET Version
9.0.103
Anything else?
IDE: VSCode 1.97.2
Tools
step cli: https://github.com/smallstep/cli
The text was updated successfully, but these errors were encountered: