Load the HTTPS certificate while validating settings instead of at Kestrel bind time - #5891
Open
ramonsmits wants to merge 3 commits into
Open
ramonsmits wants to merge 3 commits into
ramonsmits wants to merge 3 commits into
Conversation
…strel bind time AddServiceControlHttps loaded the certificate inside the ConfigureHttpsDefaults callback, which Kestrel invokes when binding endpoints. An unusable certificate therefore failed only after RavenDB, the transport and every hosted service had started and had to be torn down again. ValidateCertificateConfiguration now loads the certificate too, and the failure names the file, its size and last-modified time, and whether a password was configured, but never the password itself. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
warwickschroeder
approved these changes
Sep 15, 2026
… cause of load failures Kestrel does not verify the private key when binding, so a certificate-only PFX started fine and then failed every TLS handshake. The load-failure message now uses the base exception, which for an empty file exposes the EndOfStreamException that CryptographicException otherwise hides. The certificate is assigned in the constructor like the other properties, and the PFX-only wording replaces the stale ".pfx or .pem" references.
…Authentication Mirrors the rule Kestrel applies when binding the HTTPS endpoint, so the failure is reported during settings validation instead of after every hosted service has started. A certificate without an EKU extension is accepted, as Kestrel does.
warwickschroeder
approved these changes
Sep 17, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Is your improvement related to a problem? Please describe.
AddServiceControlHttpsloads the certificate inside theConfigureHttpsDefaultscallback, which Kestrel invokes when binding endpoints — the last step of startup. An unusable certificate therefore fails only after RavenDB, the transport and every hosted service have started and have to be torn down again. The reported error is .NET's own text, which names neither the file nor the setting that supplies the password.Two further certificate problems were not reported at all or only at bind time:
Describe the suggested solution
The certificate is now loaded and validated while
HttpsSettingsis constructed, before the host is built, andAddServiceControlHttpsuses the loaded instance. Validation rejects, in order:GetBaseException(). For an empty file that exposes the underlyingEndOfStreamExceptionthat the outerCryptographicExceptionhides; for the other cases both messages are identical.Every message ends with the same escape hatch: set
Https.Enabledtofalseto start without HTTPS while investigating.The stale ".pfx or .pem" wording in the property documentation and the required-path message was replaced with PKCS#12 / .pfx, which is what the loader accepts.
Describe alternatives you've considered
Improving only the message and leaving the load where it is: keeps the discarded startup work and the ungraceful teardown that follows a failed
Host.StartAsync.Leaving the EKU rule to Kestrel: it is the last certificate failure that would still surface only at bind time, and the check is a few lines that follow Kestrel's rule exactly.
Additional context
The test fixture used an empty
Path.GetTempFileName()as a stand-in certificate, which only worked because nothing opened it; it now generates real self-signed PFX files, optionally with a password or a specific EKU. Tests added for loading, a wrong password, and a client-authentication-only EKU. The private key check has no dedicated test since it only forwardsX509Certificate2.HasPrivateKey.