3
votes

I'm receiving an error "HTTP Error 502.5 - Process Failure"/ "Operation returned an invalid status code 'Forbidden'" when attempting to access Azure Key Vault with Managed Service Identity. It works when debugging in Visual Studio, but when published to a Azure web app, it returns the 502.5 error.

I suspect it's related to permissions to Azure Key Vault. As I can run this locally in Visual Studio (and it's a new Key Vault) - I know I have permission. I'm not sure what user the web app is running as in Azure, and suspect the web app needs access to the key vault, but I was expecting this to be handled by enabling "Managed Service Identity".

How do I configure my application correctly to use Managed Service Identity to access the key vault?

Steps to reproduce:

  1. Create a new resource group in Azure Portal
  2. Create an Azure Key Vault (I called it "mytestkeyvault"). Add two secrets, secret1, secret2, add some stuff in them (I used this Azure CLI script to add 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. Create a web app in Azure. Enable Managed Service Identity.

  4. Create a new ASP.NET Core 2.1 WebAPI (I named it "MyKeyVaultTest.Service").
  5. Add the NuGet packages:

    • AspNetCore.KeyVault
    • Microsoft.Azure.Services.AppAuthentication
  6. Edit the appsettings.json file to add the Key Vault URL:

    {
      "Logging": {
        "LogLevel": {
          "Default": "Warning"
        }
      },
      "AllowedHosts": "*",
      "AppSettings": {
        "KeyVaultURL": "https://mytestkeyvault.vault.azure.net/"
      }
    }
    
  7. In the program.cs file, edit to look like this, to connect to appsettings.json and connect to the keyvault:

    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. In the values controller, edit to look like this:

    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. Run in Visual Studio - note that the values api returns what we expect:

    ["Hello","Goodbye"]
    
  10. Publish to the project to Azure. Note that it does not work and returns:

    HTTP Error 502.5 - Process Failure

    Full stack of error:

    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\1\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\1\s\MyKeyVaultTest\MyKeyVaultTest.Service\Program.cs:line 17
    
1
you don't really need the AspNetCore.KeyVault package for this code. it is meant for the different use case and isn't a first-party nugetNeville Nazerane

1 Answers

2
votes

Enabling Managed Service Identity in the Web App creates an Identity for use within Azure. You still need to grant that Identity the necessary permission(s) on the Key Vault.

Once MSI has been enabled in the Web App, it will show up as a user that can be assigned permissions within the Key Vault's permissions configuration.