Azure KeyVault for DBContext:“尚未为此DbContext配置数据库提供程序”

时间:2018-11-01 14:23:40

标签: c# azure entity-framework-core azure-keyvault

我正在使用.NET Core 2.1构建Web API。这将作为Azure Web App托管。我想将数据库连接字符串保留在我的Azure Key Vault中。这是我放入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);
        });

当我尝试向已注入dbContext的控制器进行HTTP Get操作时,出现以下错误:

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.

我认为这是因为我使用了异步lambda来从Key Vault获取连接字符串,但是,我不确定该怎么做。这是从Azure KeyVault获取连接字符串以在Startup.cs中使用的正确方法吗?我应该以其他方式这样做吗?任何帮助,将不胜感激。谢谢。

1 个答案:

答案 0 :(得分:3)

配置失败的原因是因为回调现在为async void。 从lambda看,这并不明显,但实际上是开火而忘了。 当您等待密钥库客户端时,它会从回调中返回而无需配置提供程序。

对于解决方案,我认为最好将密钥库密钥添加到配置系统中,以便您可以从那里使用它们,就像它们是从JSON文件或任何其他来源传入的一样。

我前一段时间写了一篇文章:https://joonasw.net/view/aspnet-core-azure-keyvault-msi。 我在文章中使用托管身份进行身份验证,但我看到您也在使用它:)

以下是有关如何将Key Vault配置为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();

本文中的示例实际上有点冗长,因为它将在内部使用AzureServiceTokenProvider来获取令牌。

您需要Microsoft.Extensions.Configuration.AzureKeyVault才能获得Key Vault的配置提供程序。

Key Vault中的秘密命名很重要。 例如,我们将覆盖以下连接字符串:

{
  "ConnectionStrings": {
    "DefaultConnection": "..."
  }
}

您将必须创建一个名为 ConnectionStrings--DefaultConnection 的机密,并将连接字符串作为值。

然后在配置时仅使用Configuration["ConnectionStrings:DefaultConnection"]来获取连接字符串。 如果添加了Key Vault配置并找到了具有正确名称的机密,它将来自Key Vault。