Я пытаюсь настроить свое веб-приложение, размещенное в Azure, для чтения настроек из 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 в службе приложений, и я авторизовал своего пользователя 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\1\s\[csproj name]\Program.cs:line 22
at [csproj name].Program.Main(String[] args) in D:\a\1\s\[csproj name]\Program.cs:line 16
Я проверил, существуют ли переменные среды MSI_ENDPOINT и MSI_SECRET, вызвав SET из консоли отладки. 
Я также вижу переменную KEYVAULT_ENDPOINT.
Есть предложения, что может пойти не так или что попробовать дальше? Поскольку он работает локально, это, должно быть, проблема с аутентификацией, но я считаю, что он аутентифицируется локально с моим пользователем Azure, которого я авторизовал в хранилище ключей, а не как служба приложений Azure.


Я сталкивался с подобными проблемами раньше, когда системы разработки и производства работали по-разному при работе с переменными среды.
Моя первая область, на которую я должен обратить внимание в этих сценариях, - это проверить, правильно ли вы установили переменные среды с префиксом ASPNETCORE_ в своей производственной системе. Этот префикс является префиксом по умолчанию для веб-узлов ASP.NET Core.
| 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_ENDPOINTorMSI_SECRET. I only see you usingKEYVAULT_ENDPOINT
Если вы хотите явно установить префикс для чего-то другого, префикс, который вы хотите использовать, можно передать в качестве аргумента при инициализации веб-хоста через конфигурацию.
.AddEnvironmentVariables("ASPNETCORE_"); // choose your own prefix here
Спасибо, для чего нужен префикс ASPNETCORE_? MSI_ENDPOINT и MSI_SECRET читаются самим пакетом Microsoft.Azure.KeyVault для аутентификации MSI (я думаю).
@ zola25 Я не был уверен в этих двух ключах, поскольку они не были определены в вашем вопросе. Однако префикс ASPNETCORE_ является префиксом по умолчанию для веб-узлов ASP.NET Core, если вы явно не измените его.
Это хитроумно, но проблема с вашей настройкой заключается в том, что вы включили «Авторизованное приложение» при создании политики доступа для вашего KeyValut.
Вы можете увидеть это, потому что на вашем скриншоте есть «Приложение + Приложение». Я полагаю, вы создали политику, в которой ваше веб-приложение является одновременно основным и авторизованным приложением. Это своего рода петля.
Чтобы эта настройка работала, просто удалите существующую политику и создайте новую, в которой вы выбираете только участника:
Это правильный ответ, все работает нормально.
Чтобы решить эту проблему, мне пришлось добавить IP-адреса веб-приложения в брандмауэр, поскольку не все из них добавлялись, когда вы выбирали «Разрешить доверенные службы Microsoft ...»
Благодарность: https://azidentity.azurewebsites.net/post/2019/01/03/key-vault-firewall-access-by-azure-app-services
В AZ KV политики доступа ... при выборе только основного должны работать.

Другая возможность заключается в том, что субъекту службы требуются разрешения API для Key Vault. На портале Azure перейдите к субъекту-службе, затем выберите разрешения API в меню слева. Затем щелкните Добавить разрешения. Здесь вы можете выбрать Key Vault и сохранить. Это позволит коду получить секреты хранилища ключей.
Я хочу добавить сюда еще один случай с теми же симптомами / сообщениями об ошибках. Azure keyvault вернул значение "Запрещено", когда один из секретов был отключен.
У меня были все необходимые разрешения - я получал доступ к хранилищу ключей с помощью Get и List, предоставленных для секретов (я использовал только секреты) для управляемой идентификации моей службы приложений.
Получение ошибки «Доступ запрещен» сбивало с толку, и потребовалось немного поэкспериментировать, чтобы выяснить, в чем проблема. Надеюсь, это поможет кому-то, кто столкнулся с той же проблемой.
Если вы добавили политику доступа во время входа в Azure через Visual Studio, вам придется выйти и снова войти в систему, чтобы обновить свои разрешения.
Здесь это не по теме, но помните, что KeyVaultClient является IDisposable, поэтому было бы лучше заключить его с помощью "using"