Managing Secrets in .NET CORE 2.0 Apps


There are two kinds of developers: 1) the ones who have (accidentally) checked passwords and connection strings into source code repositories and 2) the ones that lie about it. It is a problem, we have all done it. It is annoying. When developing ASP.NET applications, you can set yourself up so that it will not happen as easily. In this blog post, I describe how I have started doing it.

Most Web Apps rely on "secrets" in order to work right. Examples include database connection strings, client secrets, API keys, passwords, etc. These secrets are used to access information and APIs needed by the application. The secrets can be added to configuration files such as appsettings.json or web.config, but what often happens is that these files end up getting checked into source code repositories with the secrets included. Depending on how widely the source code is shared, the secrets could now be compromised and with distributed source code management tools such as Git, it is not completely straight forward to purge these secrets from the revision history. Moreover, it is impossible to make sure they are purged from all the copies that have been checked out.

It is also quite common to need different sets of secrets when developing locally on your laptop, when you deploy for testing, and when deploying for production. Managing these different sets of secrets can add complications.

Most developers have used some system of multiple configuration files. Some are checked into the source core repository, some are excluded and only used locally etc., but mistakes happen, especially when debugging or when you are in a hurry and sooner or later, the secrets end up on GitHub and then you have a problem.

Here is my recipe for avoiding the problem:

Do not add secrets to configuration files. Ever. 

Until recently, that was easier said than done, but when working with ASP.NET CORE 2.0 applications in Visual Studio 2017, it is actually pretty easy. I will walk through how to manage a couple of user secrets for an ASP.NET application and how to specify them when we deploy that application on Azure.

I have created an empty ASP.NET CORE 2.0 MVC application in Visual Studio 2017. After creating the application, you can right-click on the Solution Explorer and find the menu item "Manage User Secrets":

When you click on that, it will open a file called "secrets.json". This file doesn't actually live in your source code folder and so it will not accidentally get checked in. If you would like to find the file, it is actually in

%APPDATA%\microsoft\UserSecrets\<userSecretsId>\secrets.json.

Where <userSecretsId> is a unique ID associated with your application.

Let us add a few secrets to this file:

 

{
  "myAppSetting": "This is my secret setting",
  "ConnectionStrings": {
    "myConnectionString": "This is my secret connection string"
  }
}

 

To access these values in the application, we can use the Microsoft.Extensions.Configuration module. In this application, go to the HomeController.cs file and add:

 

using Microsoft.Extensions.Configuration;

 

At the top and in the HomeController class definition, add something like:

 

    public class HomeController : Controller
    {
        public IConfiguration Configuration { get; set; }

        public HomeController(IConfiguration config)
        {
            Configuration = config;
        }

        //...Rest of the class definition
    }

 

Now the HomeController can use the Configuration to access the variables that we have just added to secrets.json. To illustrate this, make the following changes to the Index() function of the HomeController class:

 

        public IActionResult Index()
        {
            ViewData["myAppSetting"] = Configuration["myAppSetting"];
            ViewData["myConnectionString"] = Configuration.GetConnectionString("myConnectionString");
            return View();
        }

 

And in the Index.cshtml file, replace the contents with:

 

@{
    ViewData["Title"] = "Home Page";
}

<div>
    <h1>Secrets test application</h1>
    <b>myAppSetting:</b> @ViewData["myAppSetting"]<br/>
    <b>myConnectionString:</b> @ViewData["myConnectionString"]<br/>
</div>

 

If you then start debugging the application you should see something like this the index page below:

 

If we go ahead and publish that to an Azure Web App, we would see something like this:

 

 

 

The settings are not there as we would expect, since the secrets.json file is not deployed with the application. However, we can provide the settings as settings to the Web App:

 

 

If we hit save and refresh in the browser. The settings now show up:

 

So we now have a workflow where we can manage setting on our local development machine, but they are managed in a file that will not get checked into the repository and we can use the Web App configuration to specify the settings when deploying.

If you are using Visual Studio Team Services for CI/CD and you want to set your secrets as part of the deployment, you can use the Azure WebApp Configuration task from the Marketplace.

That's it. If you would like to read more about managing app secrets, have a look at this page. Let me know if you have comments/concerns/suggestions. I would also like to hear about any other schemes that you recommend for managing secrets with other environments than ASP.NET CORE 2.0.


Comments (4)

  1. Trond Hindenes says:

    How does this work outside of Azure webapp? Environment variables or similar?

    1. mihansen says:

      @Trond, if you are deploying outside an Azure Web App, you need to provide the settings in the web.config or appsettings.json file when you deploy. Or you could have another file that you read during configuration for that deployment environment. At least that is how I would do it. Hope that helps.

  2. Andrew says:

    And if you’re using Docker, you can take advantage of the Secrets management functionality to allocate secrets to your .NET Core apps 🙂 … Docker secrets are encrypted at-rest, encrypted in-transit and mounted in-memory via tempfs -> https://docs.docker.com/engine/swarm/secrets/

    1. mihansen says:

      @Andrew, good point.

Skip to main content