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

使用Azure.Security.KeyVault.Secrets的Net核心密钥库配置,azure,azure-keyvault,azure-managed-identity,Azure,Azure Keyvault,Azure Managed Identity,我发现使用托管标识连接Azure KeyVault很容易。文档说明了如何执行此操作: var azureServiceTokenProvider = new AzureServiceTokenProvider(); var keyVaultClient = new KeyVaultClient( new KeyVaultClient.AuthenticationCallback(

我发现使用托管标识连接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相关

[编辑] 我发现以下代码可以使用SDK 4中的托管标识获取azure KeyVault机密。但是,我不知道如何将其添加到我的配置中。它过去是使用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>();
                });
        }
return Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((上下文,配置)=>
{
var azureCredentialOptions=新的DefaultAzureCredentialOptions();
var凭证=新的DefaultAzureCredential(azureCredentialOptions);
var secretClient=newsecretclient(new System.Uri(“https://mykeyvault.vault.azure.net/(证书),;
var secret=secretClient.GetSecret(“StorageConnectionString”);
config.AddAzureKeyVault()
})
.ConfigureWebHostDefaults(webBuilder=>
{
webBuilder.UseStartup();
});
}

我用的是这样的东西

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";
var keyVaultEndpoint=GetKeyVaultEndpoint();
如果(!string.IsNullOrEmpty(keyVaultEndpoint))
{
//传递适当的连接字符串
var azureServiceTokenProvider=新建
AzureServiceTokenProvider(certThumbprintConnectionString);
var keyVaultClient=new keyVaultClient(new keyVaultClient.AuthenticationCallback(
azureServiceTokenProvider.KeyVaultTokenCallback);
config.AddAzureKeyVault(KeyVault端点、KeyVault客户端、新的DefaultKeyVault SecretManager());
}
私有静态字符串GetKeyVaultEndpoint()=>“https://.vault.azure.net";

首先,Microsoft.Azure.KeyVault没有被弃用,而是被取代。使用旧的nuget包仍然是一个有效的选项

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

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

如果您真的想使用Azure.Security.KeyVault.Secrets,您可以实现自己的

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

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

新的密钥保管库机密包使用了
IAsyncEnumerable
,因此您需要将项目更新为目标C#8.0:使用
8.0
更新csproj文件

Azure密钥保险库机密配置代码:

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;
    }
}
公共接口IKeyVaultSecretManager
{
bool ShouldLoad(SecretProperties secret);
字符串GetKey(KeyVaultSecret);
}
公共类DefaultKeyVaultSecretManager:IKeyVaultSecretManager
{
公共bool ShouldLoad(SecretProperties secret)=>true;
公共字符串GetKey(KeyVaultSecret)
=>secret.Name.Replace(“--”,ConfigurationPath.KeyDelimiter);
}
公共类AzureKeyVault配置提供程序:配置提供程序
{
私有只读加密客户端(private readonly SecretClient);;
私人只读IKeyVaultSecretManager\u manager;
public AzureKeyVault配置提供程序(SecretClient客户端、iKeyVault SecretManager管理器)
{
_client=client??抛出新ArgumentNullException(name of(client));
_manager=manager??抛出新的ArgumentNullException(nameof(manager));
}
public override void Load()=>LoadAsync().ConfigureAwait(false).GetAwaiter().GetResult();
专用异步任务LoadAsync()
{
var数据=新字典(StringComparer.OrdinalIgnoreCase);
等待foreach(在_client.getPropertiesOffSecretsAsync()中的var secretProperties)
{
if(!_manager.ShouldLoad(secretProperties)| | secretProperties?.Enabled!=true)
继续;
var secret=await\u client.GetSecretAsync(secretProperties.Name).ConfigureAwait(false);
var key=\u manager.GetKey(secret.Value);
Data.Add(key,secret.Value.Value);
}
数据=数据;
}
}
公共类AzureKeyVault配置源:IConfigurationSource
{
public SecretClient客户端{get;set;}
公共IKeyVaultSecretManager管理器{get;set;}
公共IConfigurationBuilder生成(IConfigurationBuilder)
{
返回新的AzureKeyVault配置提供程序(客户、经理);
}
}
公共静态类AzureKeyVault配置扩展
{
公共静态IConfigurationBuilder AddAzureKeyVault(
此IConfigurationBuilder配置生成器,
秘密客户端,
IKeyVaultSecretManager=null)
{
如果(configurationBuilder==null)
抛出新ArgumentNullException(nameof(configurationBuilder));
if(客户端==null)
抛出新的ArgumentNullException(nameof(client));
configurationBuilder.Add(新AzureKeyVault配置源()
{
客户=客户,
Manager=Manager??新的DefaultKeyVaultSecretManager()
});
返回配置生成器;
}
}
现在,您可以在项目中使用此配置生成器,如下所示:

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>();
}
公共类程序
{
公共静态void Main(字符串[]args)
{
CreateWebHostBuilder(args.Build().Run();
}
公共静态IWebHostBuilder CreateWebHostBuilder(字符串[]args)=>
我们
   var credential = new DefaultAzureCredential();
               
   config.AddAzureKeyVault(new System.Uri("https://mykv.vault.azure.net/"), credential);
configuration["StorageConnectionString"]
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