"HTTP Error 502.5 - Process Failure" 使用 ASP.NET Core 2.1 WebAPI 访问 Azure PaaS 中的 Azure Key Vault

"HTTP Error 502.5 - Process Failure" accessing Azure Key Vault in Azure PaaS with ASP.NET Core 2.1 WebAPI

我在尝试使用托管服务身份访问 Azure Key Vault 时收到错误 "HTTP Error 502.5 - Process Failure"/"Operation returned an invalid status code 'Forbidden'"。 在 Visual Studio,但是当发布到 Azure Web 应用程序时,它 returns 502.5 错误。

我怀疑它与 Azure Key Vault 的权限有关。 我可以 运行 在 Visual Studio 本地(这是一个新的 Key Vault) - 我知道我得到了许可。我不确定 Web 应用程序在 Azure 中是 运行 的哪个用户,并且怀疑 Web 应用程序需要访问密钥保管库,但我希望通过启用 "Managed Service Identity" 来处理这个问题。

如何正确配置我的应用程序以使用托管服务身份访问密钥保管库?

重现步骤:

  1. 在 Azure 门户中创建新资源组
  2. 创建一个 Azure Key Vault(我称之为 "mytestkeyvault")。添加两个秘密,secret1,secret2,在其中添加一些东西(我使用这个 Azure CLI 脚本来添加 hello/goodbye)

    az keyvault secret set --vault-name 'mytestkeyvault' --name 'Secret1' --value 'Hello'
    az keyvault secret set --vault-name 'mytestkeyvault' --name 'Secret2' --value 'Goodbye'
    
  3. 在 Azure 中创建 Web 应用程序。 启用托管服务身份

  4. 创建一个新的 ASP.NET Core 2.1 WebAPI(我将其命名为 "MyKeyVaultTest.Service")。
  5. 添加 NuGet 包:

    • AspNetCore.KeyVault
    • Microsoft.Azure.Services.AppAuthentication
  6. 编辑 appsettings.json 文件以添加 Key Vault URL:

    {
      "Logging": {
        "LogLevel": {
          "Default": "Warning"
        }
      },
      "AllowedHosts": "*",
      "AppSettings": {
        "KeyVaultURL": "https://mytestkeyvault.vault.azure.net/"
      }
    }
    
  7. 在 program.cs 文件中,编辑成如下所示,连接到 appsettings.json 并连接到密钥库:

    using Microsoft.AspNetCore;
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.Logging;
    
    namespace MyKeyVaultTest.Service
    {
        public class Program
        {
            public static void Main(string[] args)
            {
                CreateWebHostBuilder(args).Build().Run();
            }
    
            public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
                WebHost.CreateDefaultBuilder(args)
                    .ConfigureAppConfiguration((context, config) =>
                    {
                        IConfigurationRoot builtConfig = config.Build();
                        ConfigurationBuilder keyVaultConfigBuilder = new ConfigurationBuilder();
                        keyVaultConfigBuilder.AddAzureKeyVault(builtConfig["AppSettings:KeyVaultURL"]);
                        IConfigurationRoot keyVaultConfig = keyVaultConfigBuilder.Build();
                        config.AddConfiguration(keyVaultConfig);
                    })
                    .UseStartup<Startup>();
        }
    }
    
  8. 在值控制器中,编辑成如下所示:

    using Microsoft.AspNetCore.Mvc;
    using Microsoft.Extensions.Configuration;
    using System.Collections.Generic;
    
    namespace MyKeyVaultTest.Service.Controllers
    {
        [Route("api/[controller]")]
        [ApiController]
        public class ValuesController : ControllerBase
        {
            private readonly IConfiguration _configuration;
    
            public ValuesController(IConfiguration configuration)
            {
                _configuration = configuration;
            }
    
            // GET api/values
            [HttpGet]
            public ActionResult<IEnumerable<string>> Get()
            {
                string secret1 = _configuration["Secret1"];
                string secret2 = _configuration["Secret2"];
    
                return new string[] { secret1, secret2 };
            }        
        }
    }
    
  9. 运行 in Visual Studio - 请注意值 api returns 我们期望的值:

    ["Hello","Goodbye"]
    
  10. 将项目发布到 Azure。请注意,它不起作用 returns:

    HTTP 错误 502.5 - 进程失败

    满栈错误:

    Description: The process was terminated due to an unhandled exception.
    Exception Info: 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 MyKeyVaultTest.Service.Program.&lt;&gt;c.&lt;CreateWebHostBuilder&gt;b__1_0(WebHostBuilderContext context, IConfigurationBuilder config) in D:\a\s\MyKeyVaultTest\MyKeyVaultTest.Service\Program.cs:line 27
       at Microsoft.AspNetCore.Hosting.WebHostBuilder.BuildCommonServices(AggregateException&amp; hostingStartupErrors)
       at Microsoft.AspNetCore.Hosting.WebHostBuilder.Build()
       at MyKeyVaultTest.Service.Program.Main(String[] args) in D:\a\s\MyKeyVaultTest\MyKeyVaultTest.Service\Program.cs:line 17
    

在 Web 应用程序中启用托管服务身份会创建一个在 Azure 中使用的身份。您仍然需要授予该身份对 Key Vault 的必要权限。

在 Web 应用程序中启用 MSI 后,它将显示为可以在 Key Vault 的权限配置中分配权限的用户。