使用Azure.Security.KeyVault.Secrets的网络核心密钥库配置

时间:2020-06-21 18:48:08

标签: 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());
        

然后我意识到它需要已弃用的软件包Microsoft.Azure.KeyVault。因此,我正在努力找出如何使用SDK 4进行上述操作。我找到的所有文档都与SDK 3有关。

enter image description here

[编辑] 我发现以下代码可以通过SDK 4的Managed Identiy获得天蓝色的KeyVault Secret。但是,我看不到如何将其添加到我的配置中。以前是使用Microsoft.Extensions.Configuration.AzureKeyVault软件包中的 config.AddAzureKeyVault()完成的,但是它与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>();
                });
        }

5 个答案:

答案 0 :(得分:6)

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

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

然后使用它

configuration["StorageConnectionString"]

答案 1 :(得分:4)

第一件事是Microsoft.Azure.KeyVault未被弃用,而是被替换了。使用旧的nuget包仍然是有效的选择。

我想将来Microsoft.Extensions.Configuration.AzureKeyVault nuget软件包将使用新的Azure.Security.KeyVault.Secrets软件包。

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

如果您确实想使用Azure.Security.KeyVault.Secrets,则可以实现自己的custom configuration builder

我看了github上现有的密钥库配置代码,这是您可以使用的简化/修改版本。

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

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

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;
    }
}

您现在可以像这样在项目中使用此配置生成器:

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>();
}

答案 2 :(得分:0)

我正在使用类似的东西

var keyVaultEndpoint = GetKeyVaultEndpoint();
if (!string.IsNullOrEmpty(keyVaultEndpoint))
{
 // Pass appropriate connection string 
 var azureServiceTokenProvider = new 
 AzureServiceTokenProvider(certThumbprintConnectionString);
 var keyVaultClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(
 azureServiceTokenProvider.KeyVaultTokenCallback));
 config.AddAzureKeyVault(keyVaultEndpoint, keyVaultClient, new DefaultKeyVaultSecretManager());
}
private static string GetKeyVaultEndpoint() => "https://<<key-vault-name>>.vault.azure.net";

答案 3 :(得分:0)

有关您的信息,如果您在App Service或Azure Functions应用程序设置中使用Azure Key Vault机密,则不必添加额外的代码即可获取密钥库的值。

您只需要使用密钥库引用来更改您的应用程序设置值(在azure门户中)。

有关步骤,请查看https://docs.microsoft.com/en-us/azure/app-service/app-service-key-vault-references

使用密钥库引用的设置示例: { “ name”:“ DatabaseSettings:ConnectionString”, “值”:“ @ Microsoft.KeyVault(SecretUri = https://myvault.vault.azure.net/secrets/DatabaseConnectionSettingSecret/ec96f02080254fxxxxxxxxxxxxxxx)”, “ slotSetting”:否 }

但这不适用于本地开发,而是应使用纯秘密值。但是对我来说,这没关系,因为您的本地开发使用了不同的秘密值,并且您没有将local.settings.json添加到源代码控制中。

答案 4 :(得分:0)

带有第 4 版库的最新工作解决方案。我的堆栈是 .netcore 3.1,我在 Azure Web 应用程序中使用它从 Azure KeyVault 访问机密。

第一件事 - 完成这个MS Doc link

using Azure.Identity;
using Azure.Security.KeyVault.Secrets;
//..........

 var kvUri = "https://YOURVAULTNAME.vault.azure.net/";
 var client = new SecretClient(new Uri(kvUri), new DefaultAzureCredential());
 KeyVaultSecret secret = client.GetSecret("SECRETNAME");
                       // Can also use await.....GetSecretAsync()      

 this.ConnectionString = secret.Value.ToString();
 \\thats my internal variable, secret.Value.ToString() is required value

我假设你有

  1. 在 Azure 中创建了 keyVault
  2. 在应用服务中创建托管身份(在应用服务中使用“身份”选项)
  3. 在 Azure KeyVault 中添加了上述标识(“访问策略”选项)