0
votes

Problem statement: retrieve and use a sensitive value (say a database connection string) stored in azure key vault programmatically in a web/console c# app.

I understand you can register an app in AAD and use its client id and client secret to generate an ad token programmatically which can be used to call/access azure key vault secrets.

My confusion is that the client secret itself is a sensitive ‘password’ which you would want to store in the key vault. Once someone knows the client secret they can access all secrets in the key vault. So how does it make sense to create a new secret (client secret) to store and access the original secret? (Can someone pls explain the logic behind this? Thanks!

2

2 Answers

8
votes

This is the problem of bootstrapping. How do you get access to the secret store without using a secret?

If you run your app in Azure, the answer is pretty simple. Use Managed identities.

If not running in Azure, an interactive app can access Key Vault on behalf of the current user. This does require that the user has access to the Key Vault secrets.

Another approach would be to use a certificate instead of a client secret.

1
votes

If you host your app on Azure, you can use managed identities to perform authentication between services. Once the Azure configuration is done, you need to add the following in your app: it only need to store the Azure KeyVault URI - as env variable would be better.

The following code uses Azure KeyVault with the AppConfiguration, so the local appsettings.json file is empty:

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.ConfigureAppConfiguration((hostingContext, configBuilder) =>
            {
                if (hostingContext.HostingEnvironment.IsDevelopment()) return;

                AddAzureKeyVault(configBuilder);

                var configRoot = configBuilder.Build();
                AddAzureAppConfiguration(configBuilder, configRoot);
            });

        webBuilder.UseStartup<Startup>();
    });

private static void AddAzureKeyVault(IConfigurationBuilder configBuilder)
{
    var azureServiceTokenProvider = new AzureServiceTokenProvider();
    var keyVaultClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback));
    var keyVaultName = Environment.GetEnvironmentVariable("KEY_VAULT_NAME");

    configBuilder.AddAzureKeyVault(
        $"https://{keyVaultName}.vault.azure.net/",
        keyVaultClient,
        new DefaultKeyVaultSecretManager());
}

private static void AddAzureAppConfiguration(IConfigurationBuilder configBuilder, IConfigurationRoot configRoot)
{
    var appConfigName = configRoot["AppConfiguration-Name"];
    configBuilder.AddAzureAppConfiguration(appConfigName);
}