How to use Microsoft Azure Key Vault

Introduction

In this post I will describe how to set up and use an Azure key vault to store your secret values.

Sometimes we see secrets like storage keys and connection strings written as literals in the code of a project, such as

public static class Secrets
{
  public const string ApiKey = "MyAppKey";
  // ...
}

This doesn’t seem too bad because

  • It is the fastest way to obtain a key
  • Probably the key won’t change too often in time

But there are some serious drawbacks to this way of working as well:

  • If the key does change, code needs to be adapted and redeployed.
  • The key is plain visible in the code.
  • The key is “for ever” in the source code system, maybe even on a public repository.
  • When you change the environment (from DEV to ACC to PROD), the key will probably change as well. This becomes a problem with a hard-coded key.

It would be nice to store the key elsewhere, but what are the options?

  • The key can be stored in a configuration file. This is better already, but this file will still be readable by developers (and on the public repo).
  • The key can be stored in Azure. This is what we’re going to talk about in this article.

Prerequisites for this article

If you want to follow along with the examples, you’ll need an Azure subscription. On the Azure home page you can find the steps to create a free subscription, that will be valid for 3 months.

Introducing Azure Key Vault

We can store the following items in a Key Vault, for later use:

  • Secrets. A lot of types of data can be stored here, such as tokens, passwords, keys, …
  • Keys. Encryption keys can go here, and can be references later to encrypt / decrypt your data.
  • Certificates.

These items are stored securely in the vault, only users (or processes) with the right access rights will be able to retrieve them. This access is monitored, so you can know who accessed what, and how the performance of the Key Vault is.

KeyVault

Creating an Azure Key Vault

In the Microsoft Azure portal

image

  • Click on the “Create a resource” button at the top left.
  • In the blade that appears enter “Key Vault” in the search box and select “Key Vault” from the list below.

image

Click “Create” and fill in the necessary parameters:

  • Name: a unique name for the key vault
  • Subscription: the subscription that will contain your key vault
  • Resource group: here you can either select an existing resource group or create a new one. For this example, you may want to create a new resource group so you can clean up everything easily when you are done “playing”.
  • Location
  • Pricing tier: standard, unless you want HSM backed keys.
  • Access policies: by default the current user will be the owner of the key vault. You can add or remove permissions here.
  • Click on “Create” and the key vault will be created for you. This can take some time.

Inserting values in the Key Vault

  • Find your new key vault in Azure, and click on it. If your subscription contains a lot of objects, you may first select the resource group that the key vault is in.
  • You now see the overview page, with some useful information.
    image

    • The main important piece of information here is the DNS Name (top right).  You will need this to connect to the key vault from your code.
    • You can also see the number of requests, the average latency, and the success ratio.
    • Pro tip: make a note of the average latency as a baseline value for future requests.
  • On the left side click on “Secrets”. You will see all the currently stored secrets. If you just created the key vault, this will be empty.
  • Click on “Generate/Import” to create a new secret:
    • Upload options: manual
    • Name: Password   (for our example)
    • Value: My Secret
    • Content type: leave this empty
    • If you wish you can also set an activation date and an expiration date for this secret. We will leave this empty for our example.
    • Make sure that “enabled” is set to yes and click “Create”.

When you click on the “Secrets” button on the left again, you will now see an entry for this key.

If you prefer to do this by scripting, the next section is for you.

Setting up the key vault using Azure Cloud Shell

Using a script to create an Azure object makes it repeatable. If you have multiple tenants, you can compose a script that will create the necessary objects for each tenant. This will save you time because

  • obviously, executing a script is faster than creating each object by hand
  • consistency. If everything is scripted, you can be sure that all the objects are created the same for each tenant. This can save you hours of finding configuration bugs.
  • you can keep the scripts in source control, which allows you to version them as well.

Open Cloud Shell

image

At the top, click the “Cloud Shell” icon. If this is the first time that you open the cloud shell, a wizard will be shown to set up the shell. You can choose the scripting language to use (PowerShell or Linux Bash), and then Azure will create some storage for you. There is also a fair warning that the storage will cost you some money.

For this example I will use Linux Bash.

RESOURCE_GROUP='CodeProject'
LOCATION='WestEurope'
KEY_VAULT='CPKeyVault666'

az group create --name $RESOURCE_GROUP --location $LOCATION
az keyvault create --resource-group $RESOURCE_GROUP --name $KEY_VAULT
az keyvault list
az keyvault secret set --vault-name $KEY_VAULT --name Password --value 'My Secret'
az keyvault secret list --vault-name $KEY_VAULT
az keyvault secret show --vault-name $KEY_VAULT --name Password --query value --output tsv

Using Azure Key Vault in your .NET project

Project setup

clip_image001

Using Visual Studio 2019, create a new .NET Core Console App, name it ‘KeyVault’.

NuGet packages

To use Azure Key Vault, you’ll first need to add 2 NuGet packages to your project:

  • Microsoft.Azure.KeyVault
  • Microsoft.Azure.Services.AppAuthentication

Open the “Package Manager Console” (Tools > NuGet Package Manager > Package Manager Console…) and type the following statements:

install-package Microsoft.Azure.KeyVault
install-package Microsoft.Azure.Services.AppAuthentication

In your source file you will need the following using statements:

using Microsoft.Azure.KeyVault;
using Microsoft.Azure.Services.AppAuthentication;

Reading a string from the Key Vault

To separate the concerns in the application it is best to create a separate class for this, such as:

using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.Azure.KeyVault;
using Microsoft.Azure.KeyVault.Models;
using Microsoft.Azure.Services.AppAuthentication;

namespace KeyVault
{
  public class KeyvaultUtilities : IKeyvaultUtilities     
  {
     private readonly IKeyVaultClient _keyVaultClient;         
     private readonly string _vaultBaseUrl;

     public KeyvaultUtilities(string keyvaultName)         
     {             
        _vaultBaseUrl = $"https://{keyvaultName}.vault.azure.net";             
        AzureServiceTokenProvider azureServiceTokenProvider = 
		new AzureServiceTokenProvider();             
        _keyVaultClient = new KeyVaultClient(
		new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback));         
     }
     /// <summary>         
     /// Get the value for a secret from the key vault.         
     /// </summary>         
     /// <param name="keyname"></param>         
     /// <returns></returns>         
     /// <exception cref="KeyVaultErrorException">When the key is not found, this exception is thrown.</exception>         
     public async Task<string> GetSecretAsync(string keyname)         
     {       
        try             
        {
           var secret = await _keyVaultClient.GetSecretAsync(_vaultBaseUrl, keyname)
                         .ConfigureAwait(false);
           return secret.Value;             
        }
        catch (KeyVaultErrorException kvex)
        {
           throw new KeyNotFoundException($"Keyname '{keyname}' does not seem to exist in this key vault", kvex);
        }
      }
   }
}

The purpose is to read a secret from the key vault, so that is the only method that I have implemented. You can add other key vault related methods in the class when needed.

Using this class is easy. Instead of passing the key vault name as a string, you may get it from a settings file. That will also allow you to travel easily through your development environments.

Notice that we never created a secret with a name “xyz”. Trying to retrieve this value will throw a KeyNotFoundException.

using System;
using System.Threading.Tasks;

namespace KeyVault
{
  class Program
  {
     static async Task Main(string[] args)
     {
        Console.WriteLine("Hello World!");
        IKeyvaultUtilities util = new KeyvaultUtilities("cpkeyvault666");

        string pwd = await util.GetSecretAsync("Password");
        Console.WriteLine("Password: " + pwd);
        string xyz = await util.GetSecretAsync("xyz");
        Console.WriteLine("xyz: " + pwd);
     }
  }
}

Cleanup in Azure

On the Azure Portal go back to the Cloud Shell. Delete the ‘CodeProject’ resource group:

RESOURCE_GROUP='CodeProject'
az group delete --name $RESOURCE_GROUP --yes

This will delete the ‘Codeproject’ resource group, with all of its contents. Don’t worry if you don’t perform this step, the key vault only costs you a wobbling 3 cents per 10000 operations.  You can calculate your costs here: https://azure.microsoft.com/en-us/pricing/calculator/.

You can also delete the resource group through the Azure portal.

First retrieval of the secret can be (very) slow

Retrieving the first key can take several seconds. If you are not sure that you will always need a secret from the key vault you may consider using the class Lazy<T>.

The next retrievals are fast.

For this reason you may consider to register the KeyVaultUtilities as a singleton and inject it instead of recreating it each time. How you do this will depend on the type of application that you are creating.

References

https://docs.microsoft.com/en-us/azure/key-vault/key-vault-overview

https://docs.microsoft.com/nl-be/azure/key-vault/quick-create-net

https://docs.microsoft.com/en-us/azure/key-vault/tutorial-net-create-vault-azure-web-app

About Gaston

MCT, MCSD, MCDBA, MCSE, MS Specialist
This entry was posted in .Net, Architecture, Azure, Codeproject, Development and tagged . Bookmark the permalink.

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