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

Assignees

No one assigned

    Labels

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

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions