Skip to content

WithProjectDefaults() can end up with TLS config mixing PEM and PFX certs #20019

Description

@afscrome

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

If you call WithProjectDefaults() on a resource which has been configured to use a PEM/Key file (e.g. the YARP resource)

.WithHttpsCertificateConfiguration(ctx =>
{
ctx.EnvironmentVariables["Kestrel__Certificates__Default__Path"] = ctx.CertificatePath;
ctx.EnvironmentVariables["Kestrel__Certificates__Default__KeyPath"] = ctx.KeyPath;
if (ctx.Password is not null)
{
ctx.EnvironmentVariables["Kestrel__Certificates__Default__Password"] = ctx.Password;
}
return Task.CompletedTask;
});

Then you end up with Kestrel__Certificates__Default__Path set to a PFX file but with Kestrel__Certificates__Default__KeyPath set to a KEY file

e.g.

Kestrel__Certificates__Default__KeyPath="C:\\Users\\alexanderc\\AppData\\Local\\Temp\\aspire-dcpgljts0cg.jt1\\sample-hpamyxmc\\private\\827C259F5FA6F23036837DBBDC200A758AB9F879.key"
Kestrel__Certificates__Default__Path="C:\\Users\\alexanderc\\AppData\\Local\\Temp\\aspire-dcpgljts0cg.jt1\\sample-hpamyxmc\\private\\827C259F5FA6F23036837DBBDC200A758AB9F879.pfx"

This leaves kestrel partially configured for a PFX cert, and partially a PEM cert.

Expected Behavior

When WithProjectDefaults() sets Kestrel__Certificates__Default__Path, it should either

a. Not do anything if any Kestrel__Certificates__Default_* values have been set
b. Explicitly blank out any existing Kestrel__Certificates__Default__KeyPath to ensure WithProjectDefaults() tls config fully beats any existing config

Steps To Reproduce

                  builder
                      .WithHttpsCertificateConfiguration(ctx =>
                      {
                          ctx.EnvironmentVariables["Kestrel__Certificates__Default__Path"] = ctx.CertificatePath;
                          ctx.EnvironmentVariables["Kestrel__Certificates__Default__KeyPath"] = ctx.KeyPath;
                          if (ctx.Password is not null)
                          {
                              ctx.EnvironmentVariables["Kestrel__Certificates__Default__Password"] = ctx.Password;
                          }

                          return Task.CompletedTask;
                      })
                      .WithProjectDefaults()

Exceptions (if any)

fail: Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServer[6]
      The certificate file at 'C:\Users\alexanderc\AppData\Local\Temp\aspire-dcpgljts0cg.jt1\sample-hpamyxmc\private\827C259F5FA6F23036837DBBDC200A758AB9F879.key' can not be found, contains malformed data or does not contain a certificate.
fail: Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServer[7]
      The certificate key file at 'C:\Users\alexanderc\AppData\Local\Temp\aspire-dcpgljts0cg.jt1\sample-hpamyxmc\private\827C259F5FA6F23036837DBBDC200A758AB9F879.key' can not be found, contains malformed data or does not contain a PEM encoded key in PKCS8 format.
fail: Microsoft.Extensions.Hosting.Internal.Host[11]
      Hosting failed to start
      System.InvalidOperationException: The provided key file is missing or invalid.
         at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Certificates.CertificateConfigLoader.LoadCertificate(CertificateConfig certInfo, String endpointName)
         at Microsoft.AspNetCore.Server.Kestrel.Core.TlsConfigurationLoader.LoadDefaultCertificate(ConfigurationReader configurationReader)
         at Microsoft.AspNetCore.Server.Kestrel.KestrelConfigurationLoader.Reload()
         at Microsoft.AspNetCore.Server.Kestrel.KestrelConfigurationLoader.LoadInternal()
         at Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServerImpl.BindAsync(CancellationToken cancellationToken)
         at Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServerImpl.StartAsync[TContext](IHttpApplication`1 application, CancellationToken cancellationToken)
         at Microsoft.AspNetCore.Hosting.GenericWebHostService.StartAsync(CancellationToken cancellationToken)
         at Microsoft.Extensions.Hosting.Internal.Host.<StartAsync>b__14_1(IHostedService service, CancellationToken token)
         at Microsoft.Extensions.Hosting.Internal.Host.ForeachService[T](IEnumerable`1 services, CancellationToken token, Boolean concurrent, Boolean abortOnFirstException, List`1 exceptions, Func`3 operation)

Aspire doctor output


Anything else?

No response

Activity

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

Metadata

Metadata

Labels

area-app-modelIssues pertaining to the APIs in Aspire.Hosting, e.g. DistributedApplication

Type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions