使用 KeyVault 机密覆盖 Azure 应用服务中和本地的应用程序设置
Using KeyVault secrets to override appsettings in Azure App Service and locally
正在尝试从 C# 应用服务中的 KeyVault 检索机密。
本地机器:
Visual Studio > 工具 > 选项 > Azure 服务身份验证 - 经过身份验证的 Azure 帐户
可能在你 dotnet run
的 shell 中使用 az login
如果在 vs code 等上。未检查。
蔚蓝
- 应用服务blade:
- 将应用服务标识设置为
System Assigned
- 密钥库blade:
- 已创建 KeyVault
- 创建的秘密:名称 =“Foo”
- 给自己管理机密访问策略
- 给定应用服务身份获取和列表秘密访问策略
appsettings.json
...
"KeyVaultName" : "abc123",
"Secrets": {
"One" : "@Microsoft.KeyVault(Secreturi=[uri to secret copied from Azure blade])"
}
...
Program.cs
...
using Azure.Extensions.AspNetCore.Configuration.Secrets;
using Azure.Identity;
...
public static IHostBuilder CreateHostBuilder(string[] args)
{
return Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((context, config) =>
{
var builtConfig = config.Build();
var secretClient = new SecretClient(
new Uri($"https://{builtConfig["KeyVaultName"]}.vault.azure.net/"),
new DefaultAzureCredential());
config.AddAzureKeyVault(secretClient, new KeyVaultSecretManager());
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
结果
我刚刚得到 @Microsoft ...
值,我希望它映射到密钥库中的值。
似乎有些不对劲,因为我必须两次定义 keyvault 的名称,一次在 SecretClient 中,一次在 @Microsoft.KeyVault 引用中。
看来我混合了两种从 KeyVault 获取机密的方法。
配置提供商
我在 Program.cs
中添加的是一个将机密映射到配置集合中的配置提供程序。在 Startup.cs
中放置一个断点并检查配置集合中的值验证了这一点。
我应该做的是将秘密命名为 Secret--One
,它将映射并覆盖本地配置值 { "Secret: { "One" : "..." } }
。不能使用环境变量配置映射中使用的 :
或 __
,因为这些字符在机密名称中不受支持。
感觉我在这里仍然遗漏了一些东西,所以请在评论或其他答案中更新。
应用设置中的 KeyVault 参考
另一方面,如果您想使用在 Azure 应用程序设置(应用服务配置)边栏选项卡上设置的环境变量来覆盖配置值,则可以使用 KeyVault 引用。
这个问题是您仍然需要另一种方法来确保您不会在本地保守秘密并冒着将它们提交给源代码控制的风险。
有关此方法的详细信息,请参阅 。
参考资料
我喜欢做的是让正常的配置首先发生在强类型对象上。所以如果我有一个包含秘密的配置,但它也有一些东西可以留在这样的配置中:
"ComplianceSettings": {
"Url": "https://www.somecomplianceservice.com",
"Password": "Stored In Azure key vault",
"UserName": "Stored In Azure key vault"
}
所以我让它正常读取:
var complianceSettingsConfig = configuration.GetSection(Constants.ComplianceSettingsKey); // constant value is "ComplianceSettings"
services.Configure<ComplianceSettings>(complianceSettingsConfig);
ComplianceSettings 只是一个具有 Url、密码、用户名属性
的 Poco
那么只要我 program.cs 像这样正确设置:
.ConfigureAppConfiguration((context, builder) =>
{
var configuration = builder.Build();
var azureServiceTokenProvider = new AzureServiceTokenProvider();
var keyVaultClient = new KeyVaultClient(
new KeyVaultClient.AuthenticationCallback(
azureServiceTokenProvider.KeyVaultTokenCallback));
builder.AddAzureKeyVault(
configuration["KeyVault:KeyVaultUrl"],
keyVaultClient,
new DefaultKeyVaultSecretManager());
})
“KeyVault:KeyVaultUrl”只是 appsettings.json 中的另一个配置条目,因为 section:key 如下所示:
"KeyVault": {
"KeyVaultUrl": "https://<your-url-to-kv>.vault.azure.net/"
}
如果您在控制器的构造函数中注入 IOptions,您将看到您拥有所有本地值和来自 Azure KeyVault 的 NONE。我认为这是您的实际问题....如果不是,那么也许这对其他人有帮助 ;)
发生的事情是,所有这些 services.Configure() 事情都发生在 Azure 数据存在之前。所以我们需要像这样挂钩 PostConfigure 来覆盖 keyvault 中的值:
services.PostConfigure<ComplianceSettings>(options =>
{
options.UserName = configuration.GetValue<string>(Constants.ComplianceUserNameKey);
options.Password = configuration.GetValue<string>(Constants.CompliancePasswordKey);
});
Constants.ComplianceUserNameKey 和 Constants.CompliancePasswordKey 保存密钥库中实际密钥的名称。所以基本上,当 PostConfigure 触发时,它会在 configuration.GetValue 中查找您指定的键。这次 keyvault 机密已加载到配置中,因此您只需根据它们在 keyvault 中的名称查找它们,然后用新值覆盖强类型对象中的属性。
我通常使用如下扩展方法:
public static class ServicesExtensions
{
public static IServiceCollection AddConfiguration(this IServiceCollection services, IConfiguration configuration)
{
// All configuration gets loaded here
// same as above, just gets PostConfigure if it needs
// to load secrets, if not its just a GetSection() and Configure()
}
}
然后只需添加到 ConfigureServices
services.AddConfiguration(Configuration);
希望对某人有所帮助!
您可以通过在应用服务的应用设置中引用它来使用不带任何 nuget 包的 keyvault 引用。
只需单击复制图标,即可从密钥库中复制您的机密的“uri”
在您的应用程序设置下的应用程序设置中添加一个新设置并使用此 syntax 引用 keyvault 机密。
@Microsoft.KeyVault(SecretUri=https://myvault.vault.azure.net/secrets/mysecret/)
分步指南here
正在尝试从 C# 应用服务中的 KeyVault 检索机密。
本地机器:
Visual Studio > 工具 > 选项 > Azure 服务身份验证 - 经过身份验证的 Azure 帐户
可能在你
dotnet run
的 shell 中使用az login
如果在 vs code 等上。未检查。
蔚蓝
- 应用服务blade:
- 将应用服务标识设置为
System Assigned
- 将应用服务标识设置为
- 密钥库blade:
- 已创建 KeyVault
- 创建的秘密:名称 =“Foo”
- 给自己管理机密访问策略
- 给定应用服务身份获取和列表秘密访问策略
appsettings.json
...
"KeyVaultName" : "abc123",
"Secrets": {
"One" : "@Microsoft.KeyVault(Secreturi=[uri to secret copied from Azure blade])"
}
...
Program.cs
...
using Azure.Extensions.AspNetCore.Configuration.Secrets;
using Azure.Identity;
...
public static IHostBuilder CreateHostBuilder(string[] args)
{
return Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((context, config) =>
{
var builtConfig = config.Build();
var secretClient = new SecretClient(
new Uri($"https://{builtConfig["KeyVaultName"]}.vault.azure.net/"),
new DefaultAzureCredential());
config.AddAzureKeyVault(secretClient, new KeyVaultSecretManager());
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
结果
我刚刚得到 @Microsoft ...
值,我希望它映射到密钥库中的值。
似乎有些不对劲,因为我必须两次定义 keyvault 的名称,一次在 SecretClient 中,一次在 @Microsoft.KeyVault 引用中。
看来我混合了两种从 KeyVault 获取机密的方法。
配置提供商
我在 Program.cs
中添加的是一个将机密映射到配置集合中的配置提供程序。在 Startup.cs
中放置一个断点并检查配置集合中的值验证了这一点。
我应该做的是将秘密命名为 Secret--One
,它将映射并覆盖本地配置值 { "Secret: { "One" : "..." } }
。不能使用环境变量配置映射中使用的 :
或 __
,因为这些字符在机密名称中不受支持。
感觉我在这里仍然遗漏了一些东西,所以请在评论或其他答案中更新。
应用设置中的 KeyVault 参考
另一方面,如果您想使用在 Azure 应用程序设置(应用服务配置)边栏选项卡上设置的环境变量来覆盖配置值,则可以使用 KeyVault 引用。
这个问题是您仍然需要另一种方法来确保您不会在本地保守秘密并冒着将它们提交给源代码控制的风险。
有关此方法的详细信息,请参阅
参考资料
我喜欢做的是让正常的配置首先发生在强类型对象上。所以如果我有一个包含秘密的配置,但它也有一些东西可以留在这样的配置中:
"ComplianceSettings": {
"Url": "https://www.somecomplianceservice.com",
"Password": "Stored In Azure key vault",
"UserName": "Stored In Azure key vault"
}
所以我让它正常读取:
var complianceSettingsConfig = configuration.GetSection(Constants.ComplianceSettingsKey); // constant value is "ComplianceSettings"
services.Configure<ComplianceSettings>(complianceSettingsConfig);
ComplianceSettings 只是一个具有 Url、密码、用户名属性
的 Poco那么只要我 program.cs 像这样正确设置:
.ConfigureAppConfiguration((context, builder) =>
{
var configuration = builder.Build();
var azureServiceTokenProvider = new AzureServiceTokenProvider();
var keyVaultClient = new KeyVaultClient(
new KeyVaultClient.AuthenticationCallback(
azureServiceTokenProvider.KeyVaultTokenCallback));
builder.AddAzureKeyVault(
configuration["KeyVault:KeyVaultUrl"],
keyVaultClient,
new DefaultKeyVaultSecretManager());
})
“KeyVault:KeyVaultUrl”只是 appsettings.json 中的另一个配置条目,因为 section:key 如下所示:
"KeyVault": {
"KeyVaultUrl": "https://<your-url-to-kv>.vault.azure.net/"
}
如果您在控制器的构造函数中注入 IOptions,您将看到您拥有所有本地值和来自 Azure KeyVault 的 NONE。我认为这是您的实际问题....如果不是,那么也许这对其他人有帮助 ;)
发生的事情是,所有这些 services.Configure() 事情都发生在 Azure 数据存在之前。所以我们需要像这样挂钩 PostConfigure 来覆盖 keyvault 中的值:
services.PostConfigure<ComplianceSettings>(options =>
{
options.UserName = configuration.GetValue<string>(Constants.ComplianceUserNameKey);
options.Password = configuration.GetValue<string>(Constants.CompliancePasswordKey);
});
Constants.ComplianceUserNameKey 和 Constants.CompliancePasswordKey 保存密钥库中实际密钥的名称。所以基本上,当 PostConfigure 触发时,它会在 configuration.GetValue 中查找您指定的键。这次 keyvault 机密已加载到配置中,因此您只需根据它们在 keyvault 中的名称查找它们,然后用新值覆盖强类型对象中的属性。
我通常使用如下扩展方法:
public static class ServicesExtensions
{
public static IServiceCollection AddConfiguration(this IServiceCollection services, IConfiguration configuration)
{
// All configuration gets loaded here
// same as above, just gets PostConfigure if it needs
// to load secrets, if not its just a GetSection() and Configure()
}
}
然后只需添加到 ConfigureServices
services.AddConfiguration(Configuration);
希望对某人有所帮助!
您可以通过在应用服务的应用设置中引用它来使用不带任何 nuget 包的 keyvault 引用。
只需单击复制图标,即可从密钥库中复制您的机密的“uri”
在您的应用程序设置下的应用程序设置中添加一个新设置并使用此 syntax 引用 keyvault 机密。
@Microsoft.KeyVault(SecretUri=https://myvault.vault.azure.net/secrets/mysecret/)
分步指南here