Developer certificate with custom domain names

How to generate a custom certificate that dotnet core recognizes as a valid certificate.

To be able to use custom domain names with dotnet core's inbuilt webserver; Kestrel, you must generate your own certificate. In this article, we will use the testing domain name localtest.me. What is special with localtest.me domain is that all sub-domains will point to your local machine.

Before starting ensure that the following is installed:

  • Docker client
  • Dotnet dev-certs global tool
  • Powershell or Powershell Core

To be able to generate your own certificate you need to create a certificate template, create a file with the name localhost.config with the following content, this will be used as the input to the certificate generation. The content in the template can be changed to make it work for other domains that you want to use.

[req]
distinguished_name = req_distinguished_name
req_extensions     = extensions
x509_extensions    = v3_ca

[req_distinguished_name]
commonName                  = Common Name (e.g. server FQDN or YOUR name)
commonName_default          = localhost
commonName_max              = 64

[extensions]

[v3_ca]
subjectAltName = @alt_names
basicConstraints = critical, CA:false
keyUsage = keyCertSign, cRLSign, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
1.3.6.1.4.1.311.84.1.1=DER:02

[alt_names]
DNS.1   = localhost
DNS.2   = 127.0.0.1
DNS.3   = *.localtest.me
DNS.4   = *.docker.internal

When we have the certificate template we will use OpenSSL to generate the certificate, we will run the certificate generation inside docker and export the generated certificate.

Execute the following commands to generate the certificate and installing that as a developing certificate with the dev-certs tool. To succeed you need to accept the confirmation dialogs.

$p=$PSScriptRoot; if ("" -eq $p) { $p = (Get-Location) };
docker run --rm -t -it -v "$($p):/data:rw" alpine/openssl `
    req -x509 `
    -nodes `
    -days 3650 `
    -newkey rsa:4096 `
    -keyout /data/generated-localhost.key `
    -out /data/generated-localhost.crt `
    -config /data/localhost.config `
    -subj "/CN=localhost"

$s=([System.Guid]::NewGuid());
docker run --rm -t -it -v "$($p):/data:rw" alpine/openssl `
    pkcs12 -export `
    -out /data/generated-localhost.pfx `
    -inkey /data/generated-localhost.key `
    -in /data/generated-localhost.crt `
    -passout pass:$s

dotnet dev-certs https --clean --import "$p/generated-localhost.pfx" --password $s
dotnet dev-certs https --trust
Remove-Item -Path "$($p)/generated-*" -Recurse -Force | Out-Null