Sto creando un'API Web utilizzando .NET Core 2.1. Questo sarà ospitato come app Web di Azure. Voglio mantenere la mia stringa di connessione al database in Azure Key Vault. Questo è il codice che ho inserito nel mio metodo Startup.cs ConfigureServices:
services.AddDbContext<dbContext>(async options =>
{
var keyVaultUri = new Uri("https://xxxxxxxxx.vault.azure.net/");
var azureServiceTokenProvider = new AzureServiceTokenProvider();
var keyVaultClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback));
SecretBundle connectionStringSecret = await keyVaultClient.GetSecretAsync(keyVaultUri + "secrets/DBConnectionString");
options.UseSqlServer(connectionStringSecret.Value);
});
Quando provo a fare in modo che HTTP raggiunga il mio controller a cui è stato iniettato dbContext, ottengo il seguente errore:
InvalidOperationException: No database provider has been configured
for this DbContext. A provider can be configured by overriding the
DbContext.OnConfiguring method or by using AddDbContext on the
application service provider. If AddDbContext is used, then also
ensure that your DbContext type accepts a DbContextOptions<TContext>
object in its constructor and passes it to the base constructor for
DbContext.
Suppongo che sia dovuto al mio uso del lambda async per ottenere la stringa di connessione dal Key Vault, tuttavia, non sono sicuro di cosa fare al riguardo. È questo il modo giusto per ottenere una stringa di connessione da Azure KeyVault da utilizzare in Startup.cs? Dovrei farlo in un modo diverso? Qualsiasi aiuto sarebbe apprezzato. Grazie.
Il motivo per cui la configurazione non riesce è perché il callback è ora async void
. Questo non è ovvio guardando il lambda, ma è effettivamente fuoco e dimentica. Quando si attende il client del vault della chiave, esso ritorna dalla richiamata senza configurare il provider.
Per quanto riguarda una soluzione, penso che sia meglio aggiungere i segreti chiave del vault nel sistema di configurazione in modo da poterli usare da lì come se provenissero da un file JSON o da qualsiasi altra fonte.
Ho scritto un articolo su questo tempo indietro: https://joonasw.net/view/aspnet-core-azure-keyvault-msi . Ho usato l'identità gestita per autenticarmi nel mio articolo, ma vedo che lo stai usando anche tu :)
Ecco un esempio di come è possibile configurare Key Vault come origine di configurazione in ASP.NET Core 2.x:
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.ConfigureAppConfiguration((ctx, builder) =>
{
//Build the config from sources we have
var config = builder.Build();
//Add Key Vault to configuration pipeline
builder.AddAzureKeyVault(config["KeyVault:BaseUrl"]);
})
.Build();
L'esempio che ho nell'articolo è in realtà un po 'troppo prolisso in quanto utilizzerà internamente AzureServiceTokenProvider per acquisire token.
Avrai bisogno di Microsoft.Extensions.Configuration.AzureKeyVault per ottenere il provider di configurazione per Key Vault.
La denominazione segreta in Key Vault sarà importante. Ad esempio, sostituiremo la seguente stringa di connessione:
{
"ConnectionStrings": {
"DefaultConnection": "..."
}
}
Dovresti creare un segreto denominato ConnectionStrings - DefaultConnection con la stringa di connessione come valore.
Quindi durante la configurazione è sufficiente utilizzare Configuration["ConnectionStrings:DefaultConnection"]
per ottenere la stringa di connessione. Arriverà da Key Vault se è stata aggiunta la configurazione di Key Vault e è stato trovato un segreto con il nome corretto.