【问题标题】:Net core Key vault configuration using Azure.Security.KeyVault.Secrets使用 Azure.Security.KeyVault.Secrets 的网络核心密钥保管库配置
【发布时间】:2020-10-11 15:23:40
【问题描述】:

我发现使用托管标识很容易连接到 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 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>();
                });
        }

【问题讨论】:

标签: azure azure-keyvault azure-managed-identity


【解决方案1】:

具有版本 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 中添加了上述标识(“访问策略”选项)

【讨论】:

    【解决方案2】:

    供您参考,如果您在应用服务或 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)", “插槽设置”:假 }

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

    【讨论】:

      【解决方案3】:

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

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

      然后使用它

      configuration["StorageConnectionString"]
      

      【讨论】:

      • 成功了!我尝试了很多组合,但这条线有效。我没有在任何 ms 文档中找到它。谢了!
      【解决方案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:使用 &lt;LangVersion&gt;8.0&lt;/LangVersion&gt; 更新您的 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>();
      }
      

      【讨论】:

      • 希望微软在创建新库时停止半途而废:/
      • @Thomas AddAzureKeyVault 有两个参数。
      • 我相信有一个小错字。我将 Data.Add(key, secret.Value.Value); 更改为 => data.Add(key, secret.Value.Value); 之后我可以在其他地方访问 IConfiguration 的 configuration["someKey"]
      【解决方案5】:

      我正在使用这样的东西,

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

      【讨论】:

      • 查看我的编辑。我想用托管身份来做这件事,现在可以工作了,但是我不知道如何将它添加到配置中
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-10-13
      • 1970-01-01
      • 2020-11-02
      • 1970-01-01
      • 2021-01-10
      • 1970-01-01
      • 2019-08-23
      相关资源
      最近更新 更多