我有一个.NET核心6辅助应用程序,我已经配置它使用Azure KayVault (新手到KeyVault)
注册服务时,我需要从保险库获得一个密钥,但我发现到keyVault服务的连接还没有启动,因此出现了典型的鸡和蛋的情况。
在ConfigureServices中注册服务时,如何访问密钥?
下面的代码示例显示了我需要获取使用LiteDB的连接字符串,但是我将有其他需要类似解决方案的用例:
IHost host = Host.CreateDefaultBuilder(args)
.ConfigureServices(services =>
{
var configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.Build();
// See notes in appsettings.josn file.
// See https://learn.microsoft.com/en-us/azure/azure-monitor/app/worker-service
var aiOptions = new ApplicationInsightsServiceOptions();
aiOptions.ConnectionString = configuration["APPINSIGHTS_CONNECTIONSTRING"];
aiOptions.EnableQuickPulseMetricStream = configuration.GetSection("ApplicationInsights").GetValue<bool>("EnableQuickPulseMetricStream");
aiOptions.EnableEventCounterCollectionModule = configuration.GetSection("ApplicationInsights").GetValue<bool>("EnableEventCounterCollectionModule");
aiOptions.EnableAppServicesHeartbeatTelemetryModule = configuration.GetSection("ApplicationInsights").GetValue<bool>("EnableAppServicesHeartbeatTelemetryModule");
aiOptions.EnableAzureInstanceMetadataTelemetryModule = configuration.GetSection("ApplicationInsights").GetValue<bool>("EnableAzureInstanceMetadataTelemetryModule");
aiOptions.EnableDependencyTrackingTelemetryModule = configuration.GetSection("ApplicationInsights").GetValue<bool>("EnableDependencyTrackingTelemetryModule");
aiOptions.EnableEventCounterCollectionModule = configuration.GetSection("ApplicationInsights").GetValue<bool>("EnableEventCounterCollectionModule");
aiOptions.EnableAdaptiveSampling = configuration.GetSection("ApplicationInsights").GetValue<bool>("EnableAdaptiveSampling");
aiOptions.EnableHeartbeat = configuration.GetSection("ApplicationInsights").GetValue<bool>("EnableHeartbeat");
aiOptions.AddAutoCollectedMetricExtractor = configuration.GetSection("ApplicationInsights").GetValue<bool>("AddAutoCollectedMetricExtractor");
services.AddApplicationInsightsTelemetryWorkerService(aiOptions);
// ------------------------
// ----- Lite DB START-----
// ------------------------
// *This doesnt work becuase the keyvault client hasnt started up yet!!!*
var connectionString = configuration.GetSection("LiteDB").GetValue<string>("ConnectionString");
// HOW DO I GET THE KEY VAUT KEY HERE???
services.AddSingleton<ILiteDatabase, LiteDatabase>(x => new LiteDatabase(connectionString));
// -----------------------
// ----- Lite DB END-----
// -----------------------
// Repository used for our own logging events throughout the business logic code base.
services.AddTransient<ILogExtension, LogExtension>();
// Add the Background Services
services.AddHostedService<AzureSignalRService>();
})
.ConfigureAppConfiguration((context, config) => // Azure KeyVault Configuration
{
if (context.HostingEnvironment.IsDevelopment() | context.HostingEnvironment.IsProduction())
{
// See https://learn.microsoft.com/en-us/aspnet/core/security/key-vault-configuration?view=aspnetcore-6.0
// See https://github.com/dotnet/AspNetCore.Docs/blob/main/aspnetcore/security/key-vault-configuration/samples/3.x/SampleApp/Startup.cs
var root = config.Build();
using var x509Store = new X509Store(StoreLocation.CurrentUser);
x509Store.Open(OpenFlags.ReadOnly);
var x509Certificate = x509Store.Certificates
.Find(
X509FindType.FindByThumbprint,
root["AzureADCertThumbprint"],
validOnly: false)
.OfType<X509Certificate2>()
.Single();
config.AddAzureKeyVault(
new Uri($"https://{root["KeyVaultName"]}.vault.azure.net/"),
new ClientCertificateCredential(
root["AzureADDirectoryId"],
root["AzureADApplicationId"],
x509Certificate));
}
})
.Build();
发布于 2022-07-16 13:39:48
方法是创建一个服务集合扩展类,并在Program.cs中指向这个类,而不是在ConfigureServices中注册该服务。
从KeyVault获取属性时需要解析appsettings.json键的任何代码现在都在工作。对我来说,这似乎很幸运,我只能假设服务扩展知道在启动的第一阶段之后返回并得到任何丢失的密钥。
Program.cs
IHost host = Host.CreateDefaultBuilder(args)
.ConfigureServices(services =>
{
var configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.Build();
// ------------------------
// ----- Lite DB START-----
// ------------------------
// ----- BAD -----
// *This doesnt work becuase the keyvault client hasnt started up yet!!!*
var connectionString = configuration.GetSection("LiteDB").GetValue<string>("Password");
// Simply returns the native value in app settings, rather than the actual key value stored in Azure KeyVault
Console.WriteLine(connectionString);
// ---------------------------------
// ----- Solution -----
// Add the IService Collection Extension, see seperate class further down...
services.AddDatabase();
// -----------------------
// ----- Lite DB END-----
// -----------------------
// Repository used for our own logging events throughout the business logic code base.
services.AddTransient<ILogExtension, LogExtension>();
// Add the Background Services
services.AddHostedService<AzureSignalRService>();
})
.ConfigureAppConfiguration((context, config) => // Azure KeyVault Configuration
{
if (context.HostingEnvironment.IsDevelopment() | context.HostingEnvironment.IsProduction())
{
// See https://learn.microsoft.com/en-us/aspnet/core/security/key-vault-configuration?view=aspnetcore-6.0
// See https://github.com/dotnet/AspNetCore.Docs/blob/main/aspnetcore/security/key-vault-configuration/samples/3.x/SampleApp/Startup.cs
var root = config.Build();
using var x509Store = new X509Store(StoreLocation.CurrentUser);
x509Store.Open(OpenFlags.ReadOnly);
var x509Certificate = x509Store.Certificates
.Find(
X509FindType.FindByThumbprint,
root["AzureADCertThumbprint"],
validOnly: false)
.OfType<X509Certificate2>()
.Single();
config.AddAzureKeyVault(
new Uri($"https://{root["KeyVaultName"]}.vault.azure.net/"),
new ClientCertificateCredential(
root["AzureADDirectoryId"],
root["AzureADApplicationId"],
x509Certificate));
}
})
.Build();
独立的IServiceCollection类:
internal static class ServiceCollectionDatabaseExtensions
{
public static IServiceCollection AddDatabase(this IServiceCollection services)
{
var config = services.BuildServiceProvider().GetService<IConfiguration>();
var password = config!.GetSection("LiteDB").GetValue<string>("Password");
Console.WriteLine(password); // This now returns the correct key vaue pulled from Azure Key Vault
var connectionString = "Filename=C:\'database.db;Connection=shared;Password=" + password;
Console.WriteLine(connectionString);
services.AddSingleton<ILiteDatabase, LiteDatabase>(x => new LiteDatabase(connectionString));
// Other services here...
return services;
}
}
发布于 2022-07-17 21:31:27
ConfigureAppConfiguration
运行在ConfigureServices
之前,因此当您配置服务时,配置已经加载。逻辑上应该是这样的:
IHost host = Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((context, config) =>
{
config.AddAzureKeyVault(...);
})
.ConfigureServices(services =>
{
...
})
.Build();
在您的ConfigureServices
方法中,您只需要重新创建包含appsettings.json文件的配置,这样它就永远不会从密钥库配置中获得秘密。还有另一个接受HostbuilderContext
的重载
.ConfigureServices((context, services) =>
{
// Get the configuration
var configuration = context.Configuration;
...
})
https://stackoverflow.com/questions/73004288
复制相似问题