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:
- Create a new resource group in Azure Portal
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'
Create a web app in Azure. Enable Managed Service Identity.
- Create a new ASP.NET Core 2.1 WebAPI (I named it "MyKeyVaultTest.Service").
Add the NuGet packages:
- AspNetCore.KeyVault
- Microsoft.Azure.Services.AppAuthentication
Edit the appsettings.json file to add the Key Vault URL:
{ "Logging": { "LogLevel": { "Default": "Warning" } }, "AllowedHosts": "*", "AppSettings": { "KeyVaultURL": "https://mytestkeyvault.vault.azure.net/" } }
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>(); } }
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 }; } } }
Run in Visual Studio - note that the values api returns what we expect:
["Hello","Goodbye"]
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.<>c.<CreateWebHostBuilder>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& 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
AspNetCore.KeyVault
package for this code. it is meant for the different use case and isn't a first-party nuget – Neville Nazerane