Skip to content

Load the HTTPS certificate while validating settings instead of at Kestrel bind time - #5891

Open
ramonsmits wants to merge 1 commit into
masterfrom
ramon/validate-https-certificate-earlier
Open

ramonsmits wants to merge 1 commit into
masterfrom
ramon/validate-https-certificate-earlier

Conversation

@ramonsmits

@ramonsmits ramonsmits commented Sep 14, 2026

Copy link
Copy Markdown
Member

Is your improvement related to a problem? Please describe.

AddServiceControlHttps loads the certificate inside the ConfigureHttpsDefaults callback, 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.

Describe the suggested solution

ValidateCertificateConfiguration() already runs before the host is built and already checks the path. It now loads the certificate as well, and AddServiceControlHttps uses the loaded instance. Failures name the file, its size and last-modified time, and whether a password was configured — never the password itself, since .NET collapses several unrelated causes into "the password may be incorrect".

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.

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. Two tests added.

…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>
// configuration error, and binding happens only after every hosted service has started.
try
{
Certificate = string.IsNullOrEmpty(CertificatePassword)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another scenario to consider is that the certificate file has no private key. This currently wont throw but just not allow any conections. Could we also check for !Certificate.HasPrivateKey and throw if false?

var message = $"The HTTPS certificate could not be loaded, so this instance cannot start. " +
$"Https.CertificatePath: '{CertificatePath}' ({file.Length} bytes, last modified {file.LastWriteTimeUtc:u}). " +
$"Https.CertificatePassword configured: {!string.IsNullOrEmpty(CertificatePassword)}. " +
$"{ex.GetType().Name}: {ex.Message} " +

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would this hide the actual issue? Should we use ex.GetBaseException()?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants