When setting up a new .NET Core project, one must be careful about where to store secret information, such as passwords and connection strings with sensitive data. Nowadays, it is very easy to start a new project and share its source code with the whole world, and likewise, it is very easy to share your secret information if you are not careful. It is of utmost importance that secrets are kept that way.

Azure makes it easy to store secrets on production websites and keeping them safe, but it’s mostly in their own development environment where most beginners struggle. If the software that you are building needs a password to connect to a database, the tooling will lead you down the path to storing it directly in the application settings. But then it would end up in the source code. Storing secrets inside source code has to be avoided at all costs!

The next best thing, and equally cheap at the price of free is to store your secrets in your own personal folder and retrieve them from there when needed. Luckily Visual Studio can do this out of the box. One important fact to be aware of before we continue is that this method does not encrypt the secret data in any way. It just stores it in your own personal folder, which is definitely safer than storing it in source code online but can still be compromised by someone who has access to your computer.

Start by right-clicking the project name inside the Solution Explorer window. The context menu will have an option to Manage User Secrets.

Project context menu shows option to manage secrets

Once you choose this option, Visual Studio will create an empty file named secrets.json inside your user folder. Now you can add as many secrets as you need inside this file. Each secret is stored as a key-value pair.

  "passwordForLifeAndEverything": "42"

All you need now is to read the value inside your code. This can be simply done by using the Configuration API.

string mySecret = Configuration["passwordForLifeAndEverything"];

When running the solution inside Visual Studio, it will automatically fetch the required data from your secrets file. Remember that this will only work for you on your own machine, and the other developers need to configure a similar setup on theirs. But the added advantage here is that everyone can have their own secrets, which is also better than sharing the same secrets with the whole team.

Secrets can also be grouped together by nesting JSON objects inside one another, such as the following secrets for a fictional mailing service.

    "MailService": {
        "Account": "dumdedum",
        "SecretKey": "SomethingLike8TGRKC4L71..."

Then you can refer to each key individually by using the colon character to symbolise the hierarchical relation between the keys, for example:

string mailAccount = Configuration["MailService:Account"];
string mailKey = Configuration["MailService:SecretKey"];

You can also read them together as a group, for example in the ConfigureServices method you can add


where MailSettings would be a class with the two mail service properties which will be automatically bound at runtime.

Secrets management is definitely an underestimated Visual Studio feature that tackle one of the most rampant credential dissemination issues inside the open-source world. This feature is also available as an extension in Visual Studio Code.

Azure DevOps provides a solution for visualising the test result history of your projects through the Dashboard. Let’s see how we can set up some charts.

Start by clicking the dashboard icon in Azure DevOps’ main menu.

Resource group access control

You can create a new dashboard if you wish, but in this case I will show you how to edit an existing one. So click on the Edit button.

Resource group access control

On the right-hand side of the screen, you should now see the Add Widget window. In the search box, type ‘test’ so that we can filter out the other widgets. Choose the Test Results Trend widget and click the Add button.

Resource group access control

This will add the widget, ready to be set up.

Resource group access control

Click on the cog icon to open the configuration window.

Resource group access control

Set it up as shown above. The important part is the selection of the build pipeline that is running the tests. Clicking the save button will produce the following chart.

Resource group access control

As you can see, it shows both the number of passed/failed tests as well as the test run duration. You can hover your mouse pointer over each column to get more information about the specific test run.

Resource group access control

Let’s add another widget. This time we’ll choose the ‘Test Results Trend (Advanced)’ widget instead. This widget allows us to view the trend over a particular period of time as opposed to the trend by build which we just saw with the other widget.

Again configure the widget as shown below.

Resource group access control

This produces the following chart, which is not particularly interesting when tests are running smoothly. Note that in some widgets, you can expand the view by clicking on the expand icon to get a larger view of the chart.

Resource group access control

This is an example from another project where there are occasional failures.

Resource group access control

That is how test charts can be added to your dashboard so that the whole team can keep an eye on the test results. Don’t forget to save the dashboard layout by clicking the ‘Done Editing’ button.

Resource group access control

Now it’s time to get serious. After adding an App Registration in step 1, giving it access to the Web App resource group in step 2, and preparing the Storage Account in step 3, we are now ready to finish the process by installing and configuring the Let’s Encrypt extension.

Let us head over to the web app where we will install the SSL certificate. Choose the relevant app from the App Service plan menu as shown here:

Finding the app settings

Inside the app itself, click on the Custom domains menu:

The Custom domains menu

And proceed by clicking the + Add custom domain button. Fill in your domain name.

Adding a custom domain

In order to add the domain name, you first have to prove that you actually own the name. I will not go into the details of buying the domain name and forwarding it to Azure in this post, but here I show one way to claim the domain ownership by using a CNAME record:

Domain verification page

The green checkmarks indicate that the domain was verified successfully. At this point, we should also be able to notice that the newly added domain name is not secure.

This domain is not secure

It is time to fix this and conclude the tutorial! While still inside the web app, scroll down until you find the extensions menu and click it:

The App extensions menu

Then click on the + Add button:

Adding a new extension

Search for the Azure Let’s Encrypt extension by SKJP from the marketplace.

Selecting the Let's Encrypt extension

And accept the legal terms:

Read and accept the legal terms

After accepting the legal terms, the OK button is enabled and you can click it to start the installation process.

Click ok to install extension

You will get a notification of the installation status:

Extension installation in progress

Once ready you will be presented with the Let’s Encrypt configuration wizard. Here you need to fill in the information of the resources that we created earlier.

The Let's Encrypt configuration wizard

The information that you need to enter is obtained as follows:

  • Tenant id was shown on the last screenshot of part 1.
  • Subscription id is shown on the last screenshot of part 2.
  • Client id in the same last screenshot of part 1.
  • Client secret on the screenshot before it.
  • Resource group access was described during part 2. This is the same resource group that we configured there.
  • WebAppName we also saw during this post.
  • For both of the connection strings, refer to the last screenshot of part 3.
  • Finally, tick the checkbox for updating the application settings.
Double-check everything once over, and click the Next button to go to the next step.

Let's Encrypt settings are being applied

After some time, an information screen about the existing and available custom domains shows up.

Existing domains

Click next to go to the final step. Here you need to pick up the domain name that the certificate will be bound to. Enter an email address where you will receive future expiry warnings and click on the Request and install certificate button.

The certificate request step

After this, the extension will generate and install the SSL certificate for you.

Certificate was installed successfully

We should now be able to see this new certificate in the Certificates page inside theTLS/SSL settings menu.

Certificate list

Back in the custom domains page, refresh to see that the domain name associated with the new certificate is now secure.

Site is now secure

To confirm that the website is really secure, just hit it through the browser and click on the padlock icon. I’m using Chrome here so other browsers will display a different icon and have a slightly different behaviour.

Browser also shows that site is secure

Great! We have an encouraging message that the connection is secure. Clicking on the Certificate icon shown above will open the detailed certificate information window. Just like what the rest of our website visitors will see, here we can also read that the certificate was issued by Let’s Encrypt.

Certificate details

While we are still on the Azure portal one final thing. Since our HTTPS connection is now secured, we can switch on the option to force the secure connection. This is done again from the TLS/SSL settings page as shown here:

Switch to toggle HTTPS only mode

Now if anyone tries to access the site through the unsecured HTTP connection, they will be redirected to the secure site. We can observe and confirm this behaviour in the network headers.

Site should now redirect to HTTPS

So that concludes our journey to install a free SSL certificate to an Azure website through the Let’s Encrypt extension. Many thanks to SJKP for sharing this useful extension with the rest of us. If you have any further questions feel free to comment below.

After setting up the app registration and role assignment, now it is time to look into obtaining some storage.

The Let’s Encrypt application will run as a Web Job, and as a web job it needs a storage account to store the required information. So head over to the Storage accounts menu and click on the + Create button.

Storage Account Icon

The storage account can be set with the cheapest configuration since the job will just run in the background without affecting the performance of your web site visitors. It can be set to standard performance, locally redundant storage, and hot access tier.

Creating a new Azure storage account

Once filled in, click on the Review + create button, and the review screen will come up. Go ahead and click on the Create button.

Confirm all storage account settings are correct

Wait until the new storage account is deployed, then hop over to the Access keys section and make a note of the storage account connection string.

Storage account connection string

We will then use all of the connection settings that we have collected so far in the last step. Just be patient and keep them safe.

In the previous post, we have configured an app registration to give us the means to identify the Let’s Encrypt app during automatic jobs. Now we will give access to the app so that it can manage the resources inside the web application for us.

Go to the resource group that contains the web app where the SSL certificate will be installed. Click on the Access control (IAM) menu:

Resource group access control

On the right-hand side of the page, you should be able to see the role assignment widget. Click on the Add button inside it:

Add role assignment button

And in the role assignment window, add the Let’s Encrypt app registration as a contributor to the resource group as shown below. To find the correct app registration, use the search functionality inside the Select field. When searching for the app name, the search results will be shown below the Select field. Once clicked in the result, the app registration will then also be shown in the Selected members list.

Add role assignment window

Click the save button to finalise granting the rights to the application. Now technically, the Let’s Encrypt app has the necessary rights to modify our resources inside the selected group.

Finding the subscription id

Before we conclude this step, since we are already inside the Resource group page, take note of the subscription ID as indicated above. We will also need this later, together with the client secret and client ID which we had copied during the first step. Then in the next step, we will set up a storage account.