Use SSL Certificates for Dotnet Core Application in Docker Containers

Using SSL to secure incoming and outgoing traffic from your server is always recommended. When you are developing locally or testing on a server, whether it is Windows or Macintosh or some distribution of Linux like CentOS, fedora, Ubuntu etc, its easy to put the certificate in one of the local directories and then ask server to use the same. However this becomes a little bit different if you are using Containers. Since Docker is the most popular container technology, it has become almost synonymous with containers. When using containers, you can many choices:
1) Map a local volume containing certificate files to the container and then refer to it from inside container
2) Copy certificate directly inside Container during image build process and then refer to it
3) Use third party servers like Nginx or load balancer to do SSL offload. Those third party servers may themselves be containerized.

In this blog post, we’ll learn steps to use SSL certificates by .NET Core inside a Docker Container. We’ll be using .NET Core’s inbuilt server Kestrel for this purpose. Kestrel is a cross-platform web server for ASP.NET Core. More details on it can be found here.

Generating Self Signed Certificate

Since getting certificates from well known Certificate Authority’s require to undergo a certain process, we’ll be using self signed certificates for this post’s purpose. However, once you have generated the self signed certificate or using the certificate issued from an internal / external Certificate Authority, the process remains the same.

Generating Self Signed Certificate for Linux based Images

It is to be noted that Kestrel server requires the certificate to be in the PFX format. It does not recognize the certificate presented in the PEM or DER format.

First, we need to generate the CSR and a key pair. For this, we can use below openssl command:

openssl req \
-newkey rsa:2048 \
-nodes \
-keyout my_web_domain.key \
-out my_web_domain.csr

where my_web_domain is the name of the domain reserved for my application. The -newkey rsa:2048 option specifies that the key should be 2048-bit, generated using the RSA algorithm. The -nodes option specifies that the private key should not be encrypted with a pass phrase.

Once above command is input, OpenSSL will prompt few basic questions to fill the Organization specific information. You’ll need to provide the same for it to get completed.

If for some reason, this process seems too cumbersome, you can utilize the online OpenSSL CSR tool provided by DigiCert at this link. It will generate the OpenSSL command which you can run on a Linux OS to generate key and CSR.

Now we need to generate certificate using above key and CSR, which can be done by using below command:

openssl x509 \
-signkey my_web_domain.key \
-in my_web_domain.csr \
-req \
-days 365 \
-out my_web_domain.crt

Here, the -days 365 option specifies that the certificate will be valid for 365 days.

Once certificate is generated, it can be converted to PFX format using the below OpenSSL command:

openssl pkcs12 \
-inkey my_web_domain.key \
-in my_web_domain.crt \
-export \
-out my_web_domain.pfx

It will ask for a password to export the certificate in PFX format. Provide the same and also note it down as we’ll need it for future use.

Generating Self Signed Certificate for Windows based Images

We can use the PowerShell commands to generate Self Signed Certificates for the Windows based .NET Core images. For this, we need to open a PowerShell prompt and then run the below commands:

Here, -Subject and -DNS specifies the name of the web_domain for your web application, -KeyAlgorithm specifies the algorithm to be used, -KeyLength specifies the key length, -NotAfter specified duration for which certificate is valid. The certificate is finally exported to the path mentioned in the $pfxFilePath and password is mentioned in the -String “YourSecurePassword” part.

Other variations of this command can be found here. That should suffice to meet most of your needs.

Use Container with SSL Certificate

As discussed above, there are essentially two ways for container to work with SSL certificate:
1) Keep SSL at local directories and then map the volume containing the certificate inside the container.
2) Import certificate inside the container during image build process.

We’ll discuss these approaches one by one.

Map local volume containing SSL Certificate with container

This is easy, since we have gone through hard part of creating SSL certificate. We can utilize the -v switch while running docker run command to map the local directory with container. It can also be mentioned as part of the Docker Swarm or Kubernetes configuration.

Below is one of the samples for docker run command:

Import Certificate inside build as part of image build process

For this, we can use well-known COPY command inside dockerfile. Below is one of the samples for same:

Maps Kestrel with Certificate

Perhaps, the most important part is how to use it with Kestrel web server. For this, we need to set below three environment variables:

ASPNETCORE_URLS – Specifies port to be used by Kestrel to listen for HTTP and HTTPS Configuration
ASPNETCORE_Kestrel__Certificates__Default__Password – Specifies the password to decrypt the certificate
ASPNETCORE_Kestrel__Certificates__Default__Path – Specifies the certificate path within container

Below example lists how to mention same as part of the Dockerfile:

For docker compose, they can be mentioned like:

It is not necessary that you need to mention your secure password directly as part of the environmental variables. It can also be mentioned as part of the source code like:

Once everything is setup properly, you can start docker container, hit the web request and check logs. It should be something like below:

verifying Kestrel is started on https

If you happen to have an ASPNET Core web app, you can browse it fine although the browser is most likely to display an certificate invalid for self-signed certificates:

aspnet web app core running on ssl

3 thoughts on “Use SSL Certificates for Dotnet Core Application in Docker Containers

  1. Nice article! I used “Map local volume containing SSL Certificate with container” strategy and it worked like a charm on my local machine. But I want to configure my app service to use a certificate in a production environment.
    How can I do that on Azure Portal?

    Like

  2. 1. Is there any settings in program.cs and startup.cs file ?

    2. How to make the container hosted site public in production?

    3. On each container restart the IP address gets changed. How to avoid this?

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s