I have a .NET Core 6 Worker App which I've configured to use Azure KayVault (newbie to KeyVault)
When registering services, I need to get a key from the vault but I'm finding that the connection to the keyVault service has not yet started, so a typical chicken aand egg situation.
How can I access a key when registering a service in ConfigureServices?
The code sample below shows I need to grab the connection string for using LiteDB, but I will have other use cases that requires a similar solution:
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();
ConfigureAppConfiguration
runs beforeConfigureServices
so when you configure your services, the configuration is already loaded. Logically iy should looks like that:In your
ConfigureServices
method, you are recreating the configuration only including appsettings.json file so it will never get the secrets from key vault configuration. There is another overload that accept theHostbuilderContext