KeyVaultErrorException:操作返回无效状态代码 'Forbidden'

KeyVaultErrorException: Operation returned an invalid status code 'Forbidden'

我正在尝试设置托管在 Azure 中的 Web 应用程序,以从 Azure KeyVault 读取设置。

我一直在关注这个指南:https://anthonychu.ca/post/secrets-aspnet-core-key-vault-msi/

该示例展示了如何使用以下配置从 KeyVault 访问应用程序设置:

public static IWebHost BuildWebHost(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
     .ConfigureAppConfiguration((ctx, builder) =>
     {
         var keyVaultEndpoint = Environment.GetEnvironmentVariable("KEYVAULT_ENDPOINT");
         if (!string.IsNullOrEmpty(keyVaultEndpoint))
         {
             var azureServiceTokenProvider = new AzureServiceTokenProvider();
             var keyVaultClient = new KeyVaultClient(
                 new KeyVaultClient.AuthenticationCallback(
                     azureServiceTokenProvider.KeyVaultTokenCallback));
             builder.AddAzureKeyVault(
                 keyVaultEndpoint, keyVaultClient, new DefaultKeyVaultSecretManager());
         }
     })
    .UseApplicationInsights()
    .UseStartup<Startup>()
    .Build();

我已将 KEYVAULT_ENDPOINT 环境变量添加到应用程序设置中。我已在应用程序服务上启用 MSI,并且已从 Key Vault 访问策略授权我的 Azure 用户和我的应用程序:

使用获取和列表操作:

并且我已将机密添加到密钥库中。 运行 在本地,我可以访问秘密。

但是我的 ASP .NET Core 站点在启动时失败,stdout 日志中显示:

Unhandled Exception: Microsoft.Azure.KeyVault.Models.KeyVaultErrorException: Operation returned an invalid status code 'Forbidden'
   at Microsoft.Azure.KeyVault.KeyVaultClient.GetSecretsWithHttpMessagesAsync(String vaultBaseUrl, Nullable`1 maxresults, Dictionary`2 customHeaders, CancellationToken cancellationToken)
   at Microsoft.Azure.KeyVault.KeyVaultClientExtensions.GetSecretsAsync(IKeyVaultClient operations, String vaultBaseUrl, Nullable`1 maxresults, CancellationToken cancellationToken)
   at Microsoft.Extensions.Configuration.AzureKeyVault.AzureKeyVaultConfigurationProvider.LoadAsync()
   at Microsoft.Extensions.Configuration.AzureKeyVault.AzureKeyVaultConfigurationProvider.Load()
   at Microsoft.Extensions.Configuration.ConfigurationRoot..ctor(IList`1 providers)
   at Microsoft.Extensions.Configuration.ConfigurationBuilder.Build()
   at Microsoft.AspNetCore.Hosting.WebHostBuilder.BuildCommonServices(AggregateException& hostingStartupErrors)
   at Microsoft.AspNetCore.Hosting.WebHostBuilder.Build()
   at Blog.Program.BuildWebHost(String[] args) in D:\a\s\[csproj name]\Program.cs:line 22
   at [csproj name].Program.Main(String[] args) in D:\a\s\[csproj name]\Program.cs:line 16

我已经通过从调试控制台调用 SET 检查了 MSI_ENDPOINT 和 MSI_SECRET 环境变量是否存在。

我还可以看到 KEYVAULT_ENDPOINT 变量。

对可能出现的问题或接下来要尝试什么有什么建议吗?因为它在本地工作,所以它一定是一个身份验证问题,但我相信它是在本地使用我在密钥保管库中授权的 azure 用户进行身份验证,而不是作为 Azure 应用程序服务。

我以前见过这样的问题,开发和生产系统在处理环境变量时的行为方式不同。

在这些情况下,我要查看的第一个方面是检查您是否在生产系统中正确地为环境变量添加了 ASPNETCORE_ 前缀。此前缀是 ASP.NET 核心网络主机的默认前缀。

| Key                                |  Value                     |
|====================================|============================|
| ASPNETCORE_KEYVAULT_ENDPOINT       |  xxxxxxxxxxxxxxxx          |
| ASPNETCORE_MSI_ENDPOINT**          |  xxxxxxxxxxxxxxxx          |
| ASPNETCORE_MSI_SECRET**            |  xxxxxxxxxxxxxxxx          |

** Note that in your code I don't ever see you using MSI_ENDPOINT or MSI_SECRET. I only see you using KEYVAULT_ENDPOINT

如果您想将前缀明确设置为其他内容,您可以在通过配置初始化虚拟主机时将要使用的前缀作为参数传递。

.AddEnvironmentVariables("ASPNETCORE_"); // choose your own prefix here

这很狡猾,但您的设置存在问题,您在为 KeyValut 创建访问策略时启用了 "Authorized application"。

您可以看到它,因为您的屏幕截图上有 "Application+Application"。我想,您创建的策略是您的 webapp 既是主要应用程序又是授权应用程序。这有点造成循环。

要使此设置生效,只需删除您现有的策略并创建一个新策略,其中您 select 只有委托人:

仅select主体并添加网络应用程序,不select授权应用程序

为了解决这个问题,我不得不将 Web 应用程序的 IP 地址添加到防火墙,因为当您 select“允许受信任的 Microsoft 服务...”时,并不是所有的 IP 地址都被添加了。

感谢:https://azidentity.azurewebsites.net/post/2019/01/03/key-vault-firewall-access-by-azure-app-services

检查以确保您正在使用的服务委托人已被添加并且对您要执行的操作具有适当的权限(Keys/Secrets 等):

检查 KeyVault 是否限制了网络访问,切换以测试这是否是问题所在:

在 AZ KV 中,访问策略...只需选择主体即可。

另一种可能性是服务主体需要 Key Vault 的 API 权限。在 Azure 门户中,转到服务主体,然后在左侧菜单中选择 API 权限。然后点击添加权限。在这里您可以选择 Key Vault 并保存。这将允许代码检索密钥保管库机密。

我想在这里添加另一个具有相同 symptoms/error 消息的案例。当其中一个机密被禁用时,Azure keyvault 返回 Forbidden。

我拥有所有必需的权限 - 我正在使用 Get 和 List 为我的应用服务的托管身份授予机密(我只使用机密)来访问密钥库。

收到“禁止访问”错误令人困惑,需要进行一些实验才能找出问题所在。希望这对遇到同样问题的人有所帮助。

如果您在通过 Visual Studio 登录 Azure 时添加了访问策略,则必须注销并重新登录以刷新您的权限。