Home > Software design >  ASP.NET Core (3.1) re-using IIS certificate in self-hosted (Kestrel) application
ASP.NET Core (3.1) re-using IIS certificate in self-hosted (Kestrel) application

Time:03-08

I have an ASP.NET Core (3.1) application which is self-hosted and running as a service. I would like to expose an HTTPS endpoint for it. On the same machine there is an IIS instaled with already configured https together with certificate: enter image description here

The certificate seems to stored in local computer certificate store: Certificate manager

I can also list it via the powershell:

> get-childitem cert:\LocalMachine\My\ | format-table NotAfter, Subject

NotAfter            Subject
--------            -------
27.10.2023 07:38:45 <irrelevant>
08.03.2022 09:52:44 CN=a7642e58-2cdf-4e9b-a277-60fad84d7c64, DC=3336d6b0-b132-47ee-a49b-3ab470a5336e
23.02.2022 21:51:53 CN=a7642e58-2cdf-4e9b-a277-60fad84d7c64, DC=3336d6b0-b132-47ee-a49b-3ab470a5336e
27.10.2031 06:48:06 CN=a7642e58-2cdf-4e9b-a277-60fad84d7c64
26.10.2024 10:41:03 E=****.com, CN=****, OU=IT, O=****, L=****, S=***, C=**

I changed the appsettings.json to use the certificate from the store:

{
  "Logging": {
    "LogLevel": {
      "Default": "Debug",
      "System": "Information",
      "Microsoft": "Warning"
    }
  },
  "AllowedHosts": "*",
  "Kestrel": {
    "EndPoints": {
      "Http": {
        "Url": "http://*:5000"
      },
      "HttpsDefaultCert": {
        "Url": "https://*:5001"
      }
    },
    "Certificates": {
      "Default": {
        "Subject": "E=****.com, CN=****, OU=IT, O=****, L=****, S=***, C=**",
        "Store": "My",
        "Location": "LocalMachine",
        "AllowInvalid": "true"
      }
    }
  }
}

However this does not seem to work. I always get the following error:

 System.InvalidOperationException: The requested certificate E=****.com, CN=****, OU=IT, O=****, L=****, S=***, C=** could not be found in LocalMachine/My with AllowInvalid setting: True

I do not know what could be the problem. The only thing that I think might be problematic is that the certificate subject actually contains newlines in the subject:
Certificate

I do not know if this is the problem and I do not know how to enter it in the appsettings.json as multiline values can not be entered.

CodePudding user response:

I refer to the documentation for configuring the SSL certificates for Asp.NetCore app running on Kestrel.

I noticed some URL and ports settings also get stored in Properties/LaunchSettings.json file.

See Here: Configure endpoints for the ASP.NET Core Kestrel web server

Further, I noticed that you have put the Certificate under Defaults. I found other ways to configure the certificate. You could try to test them.

In the following appsettings.json example:

  • Set AllowInvalid to true to permit the use of invalid certificates (for example, self-signed certificates).
  • Any HTTPS endpoint that doesn't specify a certificate (HttpsDefaultCert in the example that follows) falls back to the cert defined under Certificates:Default or the development certificate.

{
  "Kestrel": {
    "Endpoints": {
      "Http": {
        "Url": "http://localhost:5000"
      },
      "HttpsInlineCertFile": {
        "Url": "https://localhost:5001",
        "Certificate": {
          "Path": "<path to .pfx file>",
          "Password": "$CREDENTIAL_PLACEHOLDER$"
        }
      },
      "HttpsInlineCertAndKeyFile": {
        "Url": "https://localhost:5002",
        "Certificate": {
          "Path": "<path to .pem/.crt file>",
          "KeyPath": "<path to .key file>",
          "Password": "$CREDENTIAL_PLACEHOLDER$"
        }
      },
      "HttpsInlineCertStore": {
        "Url": "https://localhost:5003",
        "Certificate": {
          "Subject": "<subject; required>",
          "Store": "<certificate store; required>",
          "Location": "<location; defaults to CurrentUser>",
          "AllowInvalid": "<true or false; defaults to false>"
        }
      },
      "HttpsDefaultCert": {
        "Url": "https://localhost:5004"
      }
    },
    "Certificates": {
      "Default": {
        "Path": "<path to .pfx file>",
        "Password": "$CREDENTIAL_PLACEHOLDER$"
      }
    }
  }
}

Schema notes:

  • Endpoints names are case-insensitive. For example, HTTPS and Https are equivalent.
  • The Url parameter is required for each endpoint. The format for this parameter is the same as the top-level Urls configuration parameter except that it's limited to a single value.
  • These endpoints replace those defined in the top-level Urls configuration rather than adding to them. Endpoints defined in code via Listen are cumulative with the endpoints defined in the configuration section.
  • The Certificate section is optional. If the Certificate section isn't specified, the defaults defined in Certificates:Default are used. If no defaults are available, the development certificate is used. If there are no defaults and the development certificate isn't present, the server throws an exception and fails to start.
  • The Certificate section supports multiple certificate sources.
  • Any number of endpoints may be defined in Configuration as long as they don't cause port conflicts.

Reference: Replace the default certificate from configuration

CodePudding user response:

I've managed to track down the issue. Kestrel uses FindBySubjectName when searching for certificate.

FindBySubjectName does a sub-string search and will not match the full Subject of the certificate. If your certificate subject is something like 'CN=my-certificate' then searching for 'CN=my-certificate' will not find anything. Searching only for 'my-certificate' will work.

Additional note: In addition to specifying the correct search expression, make sure that the account under which you are running the application has sufficient permissions to read the certificate from certificate store. Certificates do have ACL so you do not have to run your app as an administrator.

  • Related