Ошибка аутентификации в хранилище ключей Azure из службы приложений
Я пытаюсь пройти аутентификацию в хранилище ключей Azure из службы приложений (веб-API), используя назначенное системой удостоверение службы приложений. В хранилище ключей Azure я создал политику доступа, которая дает службе приложений доступ к ключам, секретам и сертификатам (ограничит это позже!).
В службе приложений я пытаюсь получить токен аутентификации (см. Фрагмент кода), но GetAccessTokenAsync дает мне исключение из Microsoft.Azure.Services.AppAuthentication.AzureServiceTokenProvider с сообщением, показанным ниже.
В поисках я нашел довольно много описаний этой ошибки, но не нашел полезных советов о причине или решении.
Обратите внимание, что у меня нет проблем с аутентификацией в том же хранилище ключей с использованием субъекта-службы, но идея использования управляемого удостоверения, конечно же, заключается в том, чтобы избежать хранения учетных данных, таких как идентификатор клиента и секрет, где-либо.
var azureServiceTokenProvider = new AzureServiceTokenProvider();
string accessToken = await azureServiceTokenProvider.GetAccessTokenAsync(VaultUrl);
Client = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback));
Сообщение об исключении:
Parameters: Connection String: [No connection string specified], Resource: https://efipsexternals.vault.azure.net/, Authority: . Exception Message: Tried the following 4 methods to get an access token, but none of them worked.\r\nParameters: Connection String: [No connection string specified], Resource: https://<VAULTNAME>.vault.azure.net/, Authority: . Exception Message: Tried to get token using Managed Service Identity. Access token could not be acquired. Received a non-retryable error. MSI ResponseCode: BadRequest, Response: {\"ExceptionMessage\":\"AADSTS500011: The resource principal named https://<VAULTNAME>.vault.azure.net/ was not found in the tenant named <TENANTID>. This can happen if the application has not been installed by the administrator of the tenant or consented to by any user in the tenant. You might have sent your authentication request to the wrong tenant.\\r\\nTrace ID: 52674a60-5e9c-432c-b999-e13e326f2000\\r\\nCorrelation ID: b335c7b2-2f38-4cc0-9ec3-6662c7ee5546\\r\\nTimestamp: 2019-10-27 10:58:52Z\",\"ErrorCode\":\"invalid_resource\",\"ServiceErrorCodes\":[\"500011\"],\"StatusCode\":400,\"Message\":null,\"CorrelationId\":\"102c92f1-525a-44ee-a383-d7e40ccd2ed4\"}\r\nParameters: Connection String: [No connection string specified], Resource: https://<VAULTNAME>.vault.azure.net/, Authority: . Exception Message: Tried to get token using Visual Studio. Access token could not be acquired. Visual Studio Token provider file not found at \"D:\\local\\LocalAppData\\.IdentityService\\AzureServiceAuth\\tokenprovider.json\"\r\nParameters: Connection String: [No connection string specified], Resource: https://<VAULTNAME>.vault.azure.net/, Authority: . Exception Message: Tried to get token using Azure CLI. Access token could not be acquired. 'az' is not recognized as an internal or external command,\r\noperable program or batch file.\r\n\r\nParameters: Connection String: [No connection string specified], Resource: https://<VAULTNAME>.vault.azure.net/, Authority: https://login.microsoftonline.com/common. Exception Message: Tried to get token using Active Directory Integrated Authentication. Access token could not be acquired. Failed to get user name from the operating system.Inner Exception : The format of the specified domain name is invalid\r\n
2 ответа
Чтобы получить токен доступа с управляемой идентификацией для хранилища ключей Azure, вам просто нужно:
var azureServiceTokenProvider = new AzureServiceTokenProvider();
var keyVaultClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback));
Код string accessToken = await azureServiceTokenProvider.GetAccessTokenAsync(VaultUrl);
здесь нет необходимости, и он должен быть основной причиной вашей проблемы. Вы можете передать свой URL-адрес хранилища ключей в качестве параметра, который здесь не подходит. Правильный вариант для доступа к API keyvault:https://vault.azure.com/
. Если вы хотите использовать этот фрагмент кода, вы можете сделать следующее:
public static async Task<string> AuthenticationCallback(string authority, string resource, string scope)
{
Console.WriteLine($"authority:{authority}, resource:{resource}, scope:{scope}");
return new AzureServiceTokenProvider().GetAccessTokenAsync(resource).Result;
}
static void Main(string[] args)
{
Console.ReadLine();
string baseUrl = "your keyvault url, for example: https://jackkv.vault.azure.net/";
KeyVaultClient kvc = new KeyVaultClient(AuthenticationCallback);
SecretBundle secret = kvc.GetSecretAsync(baseUrl, "testSecret").Result;
Console.WriteLine(secret.Value);
Console.ReadLine();
}
В GetAccessTokenAsync
метод требует идентификатора ресурса, как здесь https://vault.azure.com/
.
// Instantiate a new KeyVaultClient object, with an access token to Key Vault
var azureServiceTokenProvider1 = new AzureServiceTokenProvider();
var kv = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider1.KeyVaultTokenCallback));
// Optional: Request an access token to Key Vault
var azureServiceTokenProvider2 = new AzureServiceTokenProvider();
string accessToken = await azureServiceTokenProvider2.GetAccessTokenAsync("https://vault.azure.com/").ConfigureAwait(false);
Когда вы получаете Connection String: [No connection string specified]
ошибка, попробуйте следующий способ устранения неполадок.
1. пройти RunAs=App;
в параметре connectionString в AzureServiceTokenProvider
. Таким образом, он не будет пробовать разные режимы для получения токена, и исключение будет немного лучше.
2. Установите / обновите последнюю версию Microsoft.Azure.Services.AppAuthentication
.
Для более подробной информации вы можете обратиться к этой статье.