How to Store Secrets in Azure Key Vault Using .NET Core

A Step By Step Guide to Storing App Secrets in Azure Key Vault and Keeping Secrets Out of Source Control

Published on July 06, 2017

Azure Key Vault allows you to store your application secrets securely in the cloud. It's also a great way to keep secrets out of source control - for instance - Git and GitHub.

In this tutorial with accompanying video tutorial, I'll show you how you can use ASP.NET Core versions to access your app secrets in Azure Key Vault.

The tutorial has been updated to include examples of how to configure Azure Key Vault for ASP.NET Core 2, as configuration has changed and is now even simpler in ASP.NET Core 2.

The video is only 10 minutes long and covers everything you need to know to store secrets in Azure Key Vault along with the code you need to write to read these secrets.

Specifically, I will show you how to:

  • setup an app in Azure Active Directory
  • setup a Key Vault in Azure
  • grant relevant permissions to your app
  • generate an app id and app secret in Azure for your app
  • setup secrets in Azure
  • store and read secrets in a hierarchical format similar to JSON configuration files
  • write all the code you need to write to get everything working


You can watch the tutorial below, and continue reading for all the details. Additionally, you can grab the link to the GitHub repository at the end of this post.

Watch Tutorial

Why Store Secrets in Azure Key Vault

Before we get to the lower level details, let's first look at why you should consider storing your secrets in Azure Key Vault.

  1. Keeping Secrets out of GitHub
    You should never check any secrets into source control. If you're not sure why, you should read my blog post on how a bug in the Git plugin for Visual Studio 2015 exposed my source code to GitHub and cost me $6,500 in a few hours. (The Git plugin for VS was fixed almost immediately).

  2. Just about free to use
    It only costs $0.03 per 10,000 operations. With .NET Core, the configuration values are only loaded on app startup, so this makes the number of Azure operations minimal and the cost almost nothing.

  3. Centralized Storage of Secrets
    Easy management of secrets. It's secure and easy to manage via a GUI. It's better to store secrets in a central place as opposed to in multiple configuration files. The more configuration files you have, the more you have to be concerned about as you could easily forget to add a .gitignore rule for one or more configuration files.

  4. Access control and logging
    If you need to revoke access, you can simply revoke your API key and API secret, and generate a new secret if need be. Additionally, access logging is a very nice value added future that will appeal to implementations in the enterprise.

  5. Quick and easy to implement
    Lastly, Azure Key Vault is quick and easy to implement. You can setup Azure Key Vault and implement the code in less than 20 minutes.

Why Keep Secrets Out of Source Control?

Many developers check secrets into source control. This is a practice that must be avoided at all costs. If secrets land up in a public GitHub repository, it could lead to severe financial and reputational damage for a company. If you think you're safe by checking secrets into a private repository - think again. Once you check a secret into source control, it's near impossible to ever delete it completely out of source control. Unauthorized developers could have access to API keys and other sensitive information.

Worse even: if you publish secrets to a private repository, your secrets would always be one step away from being exposed. All it would take is an accidental publish to a public repository.

The Typical Scenario For Storing Secrets in Configuration Files

The typical scenario in which developers store secrets in configuration files usually involves storing secrets in one or more configuration files and excluding these files via .gitignore rules.
The risk here is that you could lose track of configuration files and forget to add a .gitignore rule for one or more configuration files.

Storing App Secrets in Azure Key Vault - How to Store Secrets in Azure Key Vault Using .NET Core
Storing App Secrets in Azure Key Vault

A Better Solution: Store Secrets in Azure Key Vault

A better solution is to store your secrets in Azure Key Vault. It's an improvement over the previous way of storing secrets as you only need to ever be concerned over a small configuration file which includes an Azure application id and application secret. Yes, you still need to take measures to ensure that this configuration file stays out of source control. It is, however, a much better solution for storing multiple configuration files as the risk of losing track of configuration files is virtually gone. Keeping track of 1 small configuration file is much easier and more manageable compared to the alternative.

A Typical Scenario for Storing App Secrets - How to Store Secrets in Azure Key Vault Using .NET Core
A Typical Scenario for Storing App Secrets

Azure Configuration Overview

On a high level, the setup process on Azure involves the following:

  1. Create an app in Azure Active Directory
  2. Create an app secret
  3. Grant Key Vault permissions to your app in Azure Active Directory
  4. Create a new Key Vault
  5. Create an access policy in Azure Key Vault for your application
  6. Create your secrets

Create an application in Azure Active Directory

In the Azure portal, go to Azure Active Directory, then click on App registrations, then new application registration.

 

Azure Directory - New App Registration - How to Store Secrets in Azure Key Vault Using .NET Core
Azure Directory - New App Registration
Register a New Application in Azure Active Directory - Step 2 - How to Store Secrets in Azure Key Vault Using .NET Core
Register a New Application in Azure Active Directory - Step 2

Get the Application Id for your Azure Application in Active Directory

Once your application has been registered, you need to get an application id. To do this, click on App registrations under Azure Active Directory, then click on your application.
This will bring up your application details along with you application id. Copy this value as you will use it in your configuration file later.

View Azure App Registrations - How to Store Secrets in Azure Key Vault Using .NET Core
View Azure App Registrations
Get Azure Application Id - How to Store Secrets in Azure Key Vault Using .NET Core
Get Azure Application Id

Create an Application Secret for your Azure Application in Active Directory

To get your application secret, you need to create your application secret. To do this, click on the keys link on the application detail page.

Then, create a new key by giving your key a description, set an expiry and click save. Note that your secret will only be available to copy once. If you lose this secret you'll have to create a new secret and delete the old one.

Create a New App Secret in Azure - How to Store Secrets in Azure Key Vault Using .NET Core
Create a New App Secret in Azure : Click on Keys
Create a new app secret in Azure : get the secret value - How to Store Secrets in Azure Key Vault Using .NET Core
Create a new app secret in Azure : get the secret value

Grant Key Vault permissions to your app in Azure Active Directory

The next step is to grant key vault permissions to your app in Azure AD. To do this, go to your application detail page in Azure. In the settings pane, click required permissions.
Then, under the Add API Access pane, click Select an API. Then, select Azure Key Vault. Finally, check the give full access to Azure Key Vault service option and save the settings.

AD Key Vault Permissions : Step 1 - How to Store Secrets in Azure Key Vault Using .NET Core
AD Key Vault Permissions: Step 1

 

AD Key Vault Permissions: Step 2 - How to Store Secrets in Azure Key Vault Using .NET Core
AD Key Vault Permissions: Step 2 
AD Key Vault Permissions: Step 3 - How to Store Secrets in Azure Key Vault Using .NET Core
AD Key Vault Permissions: Step 3

 

AD Key Vault Permissions: Step 4 - How to Store Secrets in Azure Key Vault Using .NET Core
AD Key Vault Permissions: Step 4

Create a New Key Vault and assign an Access Policy in Azure

To create a new Key Vault in Azure, go to the Key Vault page and click on add new. Then, fill in a name for your key vault and select a subscription and resource group.
To create an access policy, click on access policies and click add new. Then, search for your app name under select principal, and select your app.
Finally, under configure from template, select Key & Secret Management.

Create a New Key Vault: Step 1 - How to Store Secrets in Azure Key Vault Using .NET Core
Create a New Key Vault: Step 1
Create a new Key Vault: Step 2 - How to Store Secrets in Azure Key Vault Using .NET Core
Create a new Key Vault: Step 2

 

Create a new Key Vault: Step 3 - How to Store Secrets in Azure Key Vault Using .NET Core
Create a new Key Vault: Step 3 
Create a new Key Vault: Step 4 - How to Store Secrets in Azure Key Vault Using .NET Core
Create a new Key Vault: Step 4

Create an app secret in Azure Key Vault

Finally, creating an app secret in Azure is the easiest part of the process. To create a secret in Azure Key Vault, go to Key Vault and click on Add.
Then, under the create a secret pane, select manual under upload options. Then simply give your secret a name and value.

Note the special syntax for keys in a hierarchical structure. A double hyphen in Azure equals a colon in .NET Core.

Create a Secret in Azure Key Vault: Step 1 - How to Store Secrets in Azure Key Vault Using .NET Core
Create a Secret in Azure Key Vault: Step 1
Create a Secret in Azure Key Vault: Step 2 - How to Store Secrets in Azure Key Vault Using .NET Core
Create a Secret in Azure Key Vault: Step 2

 

Read Azure Key Vault Secrets in .NET Core

Now that we've covered everything you need to configure on Azure, let's step into the code.

 

Install the AzureKeyVault Nuget Package for .NET Core 1.0 and 1.1 (not required for .NET Core 2.0)

install-package Microsoft.Extensions.Configuration.AzureKeyVault

 

Add an Azure Key Vault configuration file

azurekeyvault.json

{
  "azureKeyVault": {
    "vault": "keyvault-name",
    "clientId": "",
    "clientSecret": ""
  } 
}

 

Add a .gitignore rule to exclude your azurekeyvault.json from Git

.gitignore

# don't checkin azurekeyvault.json
**/azurekeyvault.json

 

ASP.NET Core 1.0 and 1.1 Configuration

The settings below are specific to ASP.NET Core 1.0 and 1.1. If you're already on .NET Core 2.0, skip to the .NET Core 2.0 section as the configuration is even simpler for .NET Core 2.0

Load the azurekeyvault.json in your startup.cs

startup.cs

public Startup(IHostingEnvironment env)
{
    var builder = new ConfigurationBuilder()
        .SetBasePath(env.ContentRootPath)
        .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
        .AddJsonFile("azurekeyvault.json", optional:false, reloadOnChange: true)
        .AddEnvironmentVariables();

    //...
}

 

Add the AddAzureKeyVault method to startup.cs

The code to read the Azure Key Vault secrets will run once on your app's startup, and live in memory for subsequent access to these secrets.

Since the AddAzureKeyVault method is chained after your local configuration files are chained, the Azure Key Vaults secrets will override any previous secrets with a similar key name.

startup.cs

public Startup(IHostingEnvironment env)
{
    var builder = new ConfigurationBuilder()
        .SetBasePath(env.ContentRootPath)
        .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
        .AddJsonFile("azurekeyvault.json", optional:false, reloadOnChange: true)
        .AddEnvironmentVariables();

    var config = builder.Build();

    builder.AddAzureKeyVault(
        $"https://{config["azureKeyVault:vault"]}.vault.azure.net/",
        config["azureKeyVault:clientId"],
        config["azureKeyVault:clientSecret"]
    );

    Configuration = builder.Build();
}

Read your Azure Key Vault Secret in .NET Core 1.0 and 1.1

startup.cs

public Startup(IHostingEnvironment env)
{
    var builder = new ConfigurationBuilder()
        .SetBasePath(env.ContentRootPath)
        .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
        .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
        .AddJsonFile("azurekeyvault.json", optional: false, reloadOnChange: true)
        .AddEnvironmentVariables();

    var config = builder.Build();

    builder.AddAzureKeyVault(
        $"https://{config["azureKeyVault:vault"]}.vault.azure.net/",
        config["azureKeyVault:clientId"],
        config["azureKeyVault:clientSecret"]
    );

    Configuration = builder.Build();

    //example of how to read value
    var connectionString = Configuration["appSettings:connectionStrings:humanKode"];
}

 

ASP.NET Core 2.0 Configuration

In ASP.NET Core 2.0, configuration has been simplified even more. Azure Key Vault support has been baked into .NET Core 2, so there's no need to install the Azure Key Vault Nuget package as is the case when you use .NET Core 1.x

The big changes are around chaining and setting up of configuration. All configuration related code has moved from startup.cs to program.cs.
In general, configuration in .NET Core 2 now only requires minimal code.

program.cs

public class Program
{
    public static void Main(string[] args)
    {
        BuildWebHost(args).Run();
    }

    public static IWebHost BuildWebHost(string[] args)
    {
        var defaultBuilder = WebHost.CreateDefaultBuilder(args)
        .ConfigureAppConfiguration(ConfigConfiguration)
        .UseStartup<Startup>()
        .Build();

        return defaultBuilder;
    }

    static void ConfigConfiguration(WebHostBuilderContext webHostBuilderContext, IConfigurationBuilder configurationBuilder)
    {
        configurationBuilder.SetBasePath(Directory.GetCurrentDirectory())
            .AddJsonFile("azurekeyvault.json", false, true)
            .AddEnvironmentVariables();

        var config = configurationBuilder.Build();

        configurationBuilder.AddAzureKeyVault(
            $"https://{config["azureKeyVault:vault"]}.vault.azure.net/",
            config["azureKeyVault:clientId"],
            config["azureKeyVault:clientSecret"]
        );
    }
}

Read your Azure Key Vault Secret in .NET Core 2.0

startup.cs

public Startup(IConfiguration configuration)
{
    Configuration = configuration;
    //example of how to read value
    var connectionString = Configuration["appSettings:connectionStrings:humanKode"];
}

 

Summary

This tutorial covered how to setup an Azure Key Vault on Azure, and the necessary code you need to write in ASP.NET Core to read Azure Key Vault secrets.
If you liked this tutorial or have any thoughts to share, please let me know in the comments below.

Source Code

You can view the source code for this tutorial on GitHub at https://github.com/thecarlo/azure-key-vault-asp-net-core

Resources