Secret manager and Azure Key vault Part 2

Recap

In the previous article, we have discussed about Secret manager and how it is useful during development lifecycle.

If you haven’t read my previous article on Secret Manager then I highly encourage you to go through

https://dotnetintellect.com/2020/04/05/secret-manager-and-azure-key-vault-part-1/

In case, you are not using Azure, I would recommend you to go for free trail by using below url

https://portal.azure.com

Introduction

Azure Key vault is a tool to securely store and access secrets. A secret can be anything which is critical for your application such as API Keys, Connection Strings, Passwords, or Certificates.

Why do we need Azure Key Vault?

  • Azure Key Vault allows you to control the distribution of secrets. It also helps in reducing the chances of accidentally leaking the secrets. Your application can securely access and retrieve the secrets using DNS url.
  • Secrets are safeguarded by Azure with Industry standard algorithms.
  • Azure Key Vault can be integrated with other Azure services such as Storage Account, Event Hubs and Log Analytics.

Note: As mentioned in part 1, Azure key vault is not recommended during local development and would highly encourage you to use secret manager.

Create Key Vault using Azure CLI

//Create resource group
az group create -n <resource group name> -l <resource group location>
//Create Key Vault
az keyvault create -n <vault-name> -g <resource group name>
//Create Secret
az keyvault secret set --vault-name <vault-name> -n "apikey" --value "apivalue"

The CLI commands are quite straightforward and have created Secret key as “apikey” and Secret value as “apivalue”.

Coding

Let’s begin by creating ASP.NET Core WebApi project. Thereafter, install nuget package

dotnet add package Microsoft.Azure.KeyVault
dotnet add package Microsoft.Azure.Services.AppAuthentication

Amend appsettings.json file

 "VaultName": "<vault-name>"

Let’s modify the program file

public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
            .ConfigureAppConfiguration((ctx,builder)=>
            {
            var env = ctx.HostingEnvironment;
            builder.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
            .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: false, reloadOnChange: true);
            builder.AddEnvironmentVariables();
            var config = builder.Build();
            if (config["VaultName"] != null)
            {
                var keyVaultEndpoint= $"https://{config["VaultName"]}.vault.azure.net/";
                    var azureServiceTokenProvider = new AzureServiceTokenProvider();
                    var keyVaultClient = new KeyVaultClient(
                        new KeyVaultClient.AuthenticationCallback(
                            azureServiceTokenProvider.KeyVaultTokenCallback));
                    builder.AddAzureKeyVault(
                        keyVaultEndpoint, keyVaultClient, new DefaultKeyVaultSecretManager());
               }
            });
}

AzureServiceTokenProvider is used to get an access token from Service Identity; whereas, during local development it uses Azure CLI or Active directory integrated authentication.

[Route("api/[controller]")]
    public class AzureVaultController : Controller
    {
        private readonly IConfiguration configuration;

        public AzureVaultController(IConfiguration configuration)
        {
            this.configuration = configuration;
        }

        // GET: api/values
        [HttpGet]
        public string GetVault()
        {
            return $"The password for API Key is:{configuration.GetValue<string>("apikey")}";
        }
    }

In the controller class, you don’t need additional code to retrieve secrets from Azure Key Vault. IConfiguration interface is sufficient to retrieve the value(s) from the vault.

After running the application, the output will be as follows

As mentioned before, Azure Key Vault shouldn’t be used during local development.

 public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
            .ConfigureAppConfiguration((ctx,builder)=>
            {
            var env = ctx.HostingEnvironment;
            builder.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
            .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: false, reloadOnChange: true);
            builder.AddEnvironmentVariables();
            var config = builder.Build();
            if (!env.IsDevelopment() && config["VaultName"] != null)
            {
                var keyVaultEndpoint= $"https://{config["VaultName"]}.vault.azure.net/";
                    var azureServiceTokenProvider = new AzureServiceTokenProvider();
                    var keyVaultClient = new KeyVaultClient(
                        new KeyVaultClient.AuthenticationCallback(
                            azureServiceTokenProvider.KeyVaultTokenCallback));
                    builder.AddAzureKeyVault(
                        keyVaultEndpoint, keyVaultClient, new DefaultKeyVaultSecretManager());
               }
            });
}

Add a condition to validate whether the host environment is not running on development environment.

I hope you like the article. In case, you find the article as interesting then kindly like and share it.

Leave a comment