使用 Azure.Security.KeyVault.Secrets 的 Net core Key Vault 配置

Sam*_*Sam 9 azure azure-keyvault azure-managed-identity

我发现使用托管标识连接到 Azure KeyVault 很容易。该文档显示了如何做到这一点:

             var azureServiceTokenProvider = new AzureServiceTokenProvider();
            var keyVaultClient = new KeyVaultClient(
                new KeyVaultClient.AuthenticationCallback(
                    azureServiceTokenProvider.KeyVaultTokenCallback));

            config.AddAzureKeyVault(
                $"https://{builtConfig["KeyVaultName"]}.vault.azure.net/",
                keyVaultClient,
                new DefaultKeyVaultSecretManager());
        
Run Code Online (Sandbox Code Playgroud)

然后我意识到它需要Microsoft.Azure.KeyVault已弃用的包。所以我正在努力弄清楚如何使用 SDK 4 执行上述操作。我找到的所有文档都与 SDK 3 相关。

在此处输入图片说明

[编辑] 我发现以下代码可以使用带有 SDK 4 的托管标识来获取 azure KeyVault Secret。但是我看不到如何将它添加到我的配置中。它曾经是通过 config.AddAzureKeyVault()Microsoft.Extensions.Configuration.AzureKeyVault 包完成的,但它与 SDK 4 SecretClient 不兼容:

  return Host.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);
                    var secret = secretClient.GetSecret("StorageConnectionString");
                    config.AddAzureKeyVault()                 
                })
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });
        }
Run Code Online (Sandbox Code Playgroud)

Sam*_*Sam 10

事实证明,我找到了使用 SDK 4 的正确方法。我必须安装包 azure.extensions.aspnetcore.configuration.secrets,然后代码很简单:

   var credential = new DefaultAzureCredential();
               
   config.AddAzureKeyVault(new System.Uri("https://mykv.vault.azure.net/"), credential);
Run Code Online (Sandbox Code Playgroud)

然后使用它

configuration["StorageConnectionString"]
Run Code Online (Sandbox Code Playgroud)


Tho*_*mas 6

首先,Microsoft.Azure.KeyVault它没有被弃用,而是被替换了。使用旧的 nuget 包仍然是一个有效的选择。

我想在未来,Microsoft.Extensions.Configuration.AzureKeyVaultnuget 包将使用新Azure.Security.KeyVault.Secrets包。

根据我的经验,我会坚持使用现有的库并等待未来的更新。

如果你真的想使用Azure.Security.KeyVault.Secrets,你可以实现你自己的自定义配置生成器

我查看了github上现有的 Key Vault 配置代码,这里有一个您可以使用的简化/修改版本。

首先安装这些 nuget 包Azure.IdentityAzure.Security.KeyVault.Secrets.

使用新的密钥保管库机密包,IAsyncEnumerable因此您需要将项目更新为面向 C#8.0:使用 .csproj 文件更新您的 csproj 文件<LangVersion>8.0</LangVersion>

Azure Key Vault Secret 配置代码:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

您现在可以在您的项目中使用此配置构建器,如下所示:

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>();
}
Run Code Online (Sandbox Code Playgroud)

  • 我相信有一个小错字。我将 `Data.Add(key, Secret.Value.Value);` 更改为 =&gt; `data.Add(key, Secret.Value.Value);` 之后我能够访问 IConfiguration 的 `configuration["someKey"]`别处。 (3认同)
  • 我*希望*微软在创建新库时停止半途而废的事情:/ (2认同)