HTTPS certificate not found

HI,

I’m trying to configure HTTPS for the admin site and the rest API’s I’ve created.
I’ve configured the appsettings.json as below:

“Kestrel”: {
“Endpoints”: {
“HTTP”: {
“Url”: “http://:5000"
},
“HTTPS”: {
“Url”: "https://
:5001”,
“Certificate”: {
“Subject”: “CN=xxx, O=xxx, L=xxx, C=xxx”,
“Store”: “Root”,
“Location”: “LocalMachine”,
“AllowInvalid”: “true”
}
}
}

I’ve installed Universal using the MSI and it runs as local system as a windows service.
However, it doesn’t start and gives the error:

Unable to start Kestrel. (fc6a528d)
System.InvalidOperationException: The requested certificate CN=xxx, O=xxx, L=xxx, C=xxx could not be found in LocalMachine/Root with AllowInvalid setting: False.

I’ve checked the certificates MMC and can see it installed.
Get-ChildItem -Path cert:\LocalMachine\root\ | Select-Object subject

Lists my certificate.
Is there any command I can run to check?

Thanks,

Product: PowerShell Universal
Version: 1.4.6

You could try to run the command Get-ChildItem -Path cert:\LocalMachine\root\ | Select-Object subject within an Automation job so it’s running as the same local system account to validate that it’s picking up the cert there.

Hi There,
I have the same issue … just cannot seem to find the certificate

I added the “Get-ChildItem -Path Cert:LocalMachine/My” command to one of my API functions and the certificate is found …

So I do not know haw to proceed …
The only way forward would be to host the service in IIS …

Any further suggestions?
Cheers Paul

I have just update to the latest version 1.5.0 … as soon I try to enable HTTPS in appsettings.json
“Kestrel”: {
“Endpoints”: {
“HTTP”: {
“Url”: “http://:5000"
},
“HttpsInlineCertStore”: {
“Url”: "https://
:5001”,
“Certificate”: {
“Subject”: “CN=xxxxxxx.dddd.ch”,
“Store”: “My”,
“Location”: “LocalMachine”,
“AllowInvalid”: “false”
}
}
},
“RedirectToHttps”: “true”
},
I get the following Exception:
2020-11-18 04:08:33 [INFO] (Hangfire.Server.BackgroundServerProcess) Server xxxxxxx:4932:502e050d has been stopped in total 771.4286 ms
Unhandled exception. System.InvalidOperationException: The requested certificate CN=xxxxxxxx.dddd.ch could not be found in LocalMachine/My with AllowInvalid setting: False.
at Microsoft.AspNetCore.Server.Kestrel.Https.CertificateLoader.LoadFromStoreCert(String subject, String storeName, StoreLocation storeLocation, Boolean allowInvalid)
at Microsoft.AspNetCore.Server.Kestrel.KestrelConfigurationLoader.LoadFromStoreCert(CertificateConfig certInfo)
at Microsoft.AspNetCore.Server.Kestrel.KestrelConfigurationLoader.LoadCertificate(CertificateConfig certInfo, String endpointName)
at Microsoft.AspNetCore.Server.Kestrel.KestrelConfigurationLoader.Load()
at Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServer.ValidateOptions()
at Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServer.StartAsync[TContext](IHttpApplication`1 application, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Hosting.GenericWebHostService.StartAsync(CancellationToken cancellationToken)
at Microsoft.Extensions.Hosting.Internal.Host.StartAsync(CancellationToken cancellationToken)
at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.RunAsync(IHost host, CancellationToken token)
at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.RunAsync(IHost host, CancellationToken token)
at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.Run(IHost host)
at Universal.Server.Program.Main(String[] args) in D:\a\universal\universal\src\Universal.Server\Program.cs:line 31

But still the cert is found when Looking it up inside an API function

Cheers Paul

I’ve done some digging into this. I actually recreated the CertificateLoader class used by ASP.NET in PowerShell. This is the class that is internally being used to look up the cert.

Here’s that script.

$allowInvalid = $true
$subject = 'localhost'
$store = [System.Security.Cryptography.X509Certificates.X509Store]::new('My', 'LocalMachine')
$store.Open('ReadOnly')

$storeCertificates = $store.Certificates;
$foundCertificates = $storeCertificates.Find('FindBySubjectName', $Subject, $allowInvalid);

function Test-IsCertificateAllowedForServerAuth
{
    param($Cert)

    $ServerAuthenticationOid = "1.3.6.1.5.5.7.3.1";
    $result = $false 

    foreach($cert in $foundCertificates)
    {
        if ($cert.Extensions)
        {
            foreach($extension in $cert.Extensions  | Where-Object { $_ -is [System.Security.Cryptography.X509Certificates.X509EnhancedKeyUsageExtension] })
            {
                $result = $true
                foreach ($oid in $extension.EnhancedKeyUsages)
                {
                    if ($oid.Value -eq $ServerAuthenticationOid)
                    {
                        return $true;
                    }
                }
            }
        }
    }
    -not $result
}

$foundCertificates | Where-Object { (Test-IsCertificateAllowedForServerAuth $_) -and $_.HasPrivateKey  }

What I found is that I needed to avoid including the CN= in the subject name. So for my CN=localhost cert, I had to use localhost in the appsettings.json.

PS C:\Users\adamr\Desktop> c:\Users\adamr\Desktop\findcert.ps1

Thumbprint                                Subject              EnhancedKeyUsageList 
----------                                -------              -------------------- 
F1F2CC29D68E05E3561293BA3955286A7AF751C3  CN=localhost         Server Authentication

PS C:\Users\adamr\Desktop> dir Cert:\LocalMachine\my


   PSParentPath: Microsoft.PowerShell.Security\Certificate::LocalMachine\my

Thumbprint                                Subject              EnhancedKeyUsageList
----------                                -------              --------------------
F1F2CC29D68E05E3561293BA3955286A7AF751C3  CN=localhost         Server Authentication

You should be able to run that script to experiment faster than trying to start the PSU server over and over again.

1 Like

Hello Adam,
first let me thank you for the fast response :slight_smile: and taking my request serious!
First I took the script ran it on my server and everything worked fine. Then I changed my appsettings.json and started the server … it worked!!!
HTTPS over Kestrel seems to work now!!

Only thing I need to investigate a bit is, that if you have more than one certificate with very similar subject names, it seems to find more than one certificate and just takes the first … which could be the wrong one …

But hey HTTPS work!! Thanks alot!!
Cheers Paul

1 Like

Working for me too.
Thank you so much :relaxed:

Same problem here.
When I run the above script, no Certficate is returned.

dir cert:\LocalMachine\My does return the certificate.

PS: dir cert:\Localmachine\my

   PSParentPath: Microsoft.PowerShell.Security\Certificate::Localmachine\my

Thumbprint                                Subject              EnhancedKeyUsageList
----------                                -------              --------------------
33A4A0564187BB3DC8892A0B61D1CCC596CAF299  CN=localhost         Serverauthenticatie

PS "Findcert.ps1"

When I add the localhost certificate to the Root store, the certificate is found.

I just use the PFX file and point to in instead of installing it to the server

{
  "Kestrel": {
    "Endpoints": {
      "HTTP": {
        "Url": "http://*:80"
      },
      "Https": {
        "Url": "https://*:443",
        "Certificate": {
          "Path": "C:\\ProgramData\\PowerShellUniversal\\Cert\\cert.pfx",
          "Password": "password",
          "AllowInvalid": "true"
        }
      }
    },
    "RedirectToHttps": "true"
  },

This is nice for renewals as I can just swap the pfx and restart the service.

Not sure if that would work for your use case.