Net core Key vault configuration using Azure.Security.KeyVault.Secrets
AS per June 2020
First thing is that Microsoft.Azure.KeyVault
is not deprecated but replaced. Using the old nuget package is still a valid option.
I imagine in the future, the Microsoft.Extensions.Configuration.AzureKeyVault
nuget package will use the new Azure.Security.KeyVault.Secrets
package.
In my experience I would stick with the existing library and wait for future updates.
If you really want to use the Azure.Security.KeyVault.Secrets
, you can implement your own custom configuration builder.
I had a look at the existing key vault configuration code on github and here is a simplified/modified version that you could use.
First install these nuget packages Azure.Identity
and Azure.Security.KeyVault.Secrets
.
The new key vault secrets package uses IAsyncEnumerable
so you need to update your project to target C#8.0: update you csproj file with <LangVersion>8.0</LangVersion>
.
Azure Key Vault Secret configuration code:
public interface IKeyVaultSecretManager
{
bool ShouldLoad(SecretProperties secret);
string GetKey(KeyVaultSecret secret);
}
public class DefaultKeyVaultSecretManager : IKeyVaultSecretManager
{
public bool ShouldLoad(SecretProperties secret) => true;
public string GetKey(KeyVaultSecret secret)
=> secret.Name.Replace("--", ConfigurationPath.KeyDelimiter);
}
public class AzureKeyVaultConfigurationProvider : ConfigurationProvider
{
private readonly SecretClient _client;
private readonly IKeyVaultSecretManager _manager;
public AzureKeyVaultConfigurationProvider(SecretClient client, IKeyVaultSecretManager manager)
{
_client = client ?? throw new ArgumentNullException(nameof(client));
_manager = manager ?? throw new ArgumentNullException(nameof(manager));
}
public override void Load() => LoadAsync().ConfigureAwait(false).GetAwaiter().GetResult();
private async Task LoadAsync()
{
var data = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
await foreach (var secretProperties in _client.GetPropertiesOfSecretsAsync())
{
if (!_manager.ShouldLoad(secretProperties) || secretProperties?.Enabled != true)
continue;
var secret = await _client.GetSecretAsync(secretProperties.Name).ConfigureAwait(false);
var key = _manager.GetKey(secret.Value);
Data.Add(key, secret.Value.Value);
}
Data = data;
}
}
public class AzureKeyVaultConfigurationSource : IConfigurationSource
{
public SecretClient Client { get; set; }
public IKeyVaultSecretManager Manager { get; set; }
public IConfigurationProvider Build(IConfigurationBuilder builder)
{
return new AzureKeyVaultConfigurationProvider(Client, Manager);
}
}
public static class AzureKeyVaultConfigurationExtensions
{
public static IConfigurationBuilder AddAzureKeyVault(
this IConfigurationBuilder configurationBuilder,
SecretClient client,
IKeyVaultSecretManager manager = null)
{
if (configurationBuilder == null)
throw new ArgumentNullException(nameof(configurationBuilder));
if (client == null)
throw new ArgumentNullException(nameof(client));
configurationBuilder.Add(new AzureKeyVaultConfigurationSource()
{
Client = client,
Manager = manager ?? new DefaultKeyVaultSecretManager()
});
return configurationBuilder;
}
}
You can now use this configuration builder in your project like that:
public class Program
{
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((context, config) =>
{
var azureCredentialOptions = new DefaultAzureCredentialOptions();
var credential = new DefaultAzureCredential(azureCredentialOptions);
var secretClient = new SecretClient(new System.Uri("https://mykeyvault.vault.azure.net/"), credential);
config.AddAzureKeyVault(secretClient);
})
.UseStartup<Startup>();
}
As it turned out, I found the proper way to do it with SDK 4. I had to install the package azure.extensions.aspnetcore.configuration.secrets
and then the code is simply :
var credential = new DefaultAzureCredential();
config.AddAzureKeyVault(new System.Uri("https://mykv.vault.azure.net/"), credential);
then to use it
configuration["StorageConnectionString"]