从应用服务对 Azure Key Vault 的身份验证失败
Authentication to Azure Key Vault from an app service fails
我正在尝试使用应用服务的系统分配身份从应用服务(Web API)向 Azure Key Vault 进行身份验证。在 Azure Key Vault 中,我创建了一个访问策略,使 App Service 可以访问密钥、机密和证书(稍后会对此进行限制!)。
在应用服务中,我尝试获取身份验证令牌(参见代码片段),但 GetAccessTokenAsync 给了我一个异常 Microsoft.Azure.Services.AppAuthentication.AzureServiceTokenProvider,消息如下所示。
通过搜索,我找到了很多关于此错误的描述,但没有关于原因或解决方案的有用提示。
请注意,我使用服务主体对同一个密钥保管库进行身份验证没有问题,但使用托管身份的想法当然是为了避免在任何地方存储客户端 ID 和机密等凭据
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
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.Pass RunAs=App;
在 AzureServiceTokenProvider
的 connectionString 参数中。这样就不会去尝试不同的方式来获取token了,异常好一点。
2.Install/update最新版本Microsoft.Azure.Services.AppAuthentication
.
更多细节,你可以参考这个article。
要为 Azure Key Vault 获取具有托管标识的访问令牌,您只需:
var azureServiceTokenProvider = new AzureServiceTokenProvider();
var keyVaultClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback));
这里不需要代码string accessToken = await azureServiceTokenProvider.GetAccessTokenAsync(VaultUrl);
,它应该是你问题的根本原因。您可以将您的 keyvault url 作为参数传递给它,这在这里不合适。访问 keyvault API 的正确方法是: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();
}
我正在尝试使用应用服务的系统分配身份从应用服务(Web API)向 Azure Key Vault 进行身份验证。在 Azure Key Vault 中,我创建了一个访问策略,使 App Service 可以访问密钥、机密和证书(稍后会对此进行限制!)。
在应用服务中,我尝试获取身份验证令牌(参见代码片段),但 GetAccessTokenAsync 给了我一个异常 Microsoft.Azure.Services.AppAuthentication.AzureServiceTokenProvider,消息如下所示。
通过搜索,我找到了很多关于此错误的描述,但没有关于原因或解决方案的有用提示。
请注意,我使用服务主体对同一个密钥保管库进行身份验证没有问题,但使用托管身份的想法当然是为了避免在任何地方存储客户端 ID 和机密等凭据
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
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.Pass RunAs=App;
在 AzureServiceTokenProvider
的 connectionString 参数中。这样就不会去尝试不同的方式来获取token了,异常好一点。
2.Install/update最新版本Microsoft.Azure.Services.AppAuthentication
.
更多细节,你可以参考这个article。
要为 Azure Key Vault 获取具有托管标识的访问令牌,您只需:
var azureServiceTokenProvider = new AzureServiceTokenProvider();
var keyVaultClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback));
这里不需要代码string accessToken = await azureServiceTokenProvider.GetAccessTokenAsync(VaultUrl);
,它应该是你问题的根本原因。您可以将您的 keyvault url 作为参数传递给它,这在这里不合适。访问 keyvault API 的正确方法是: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();
}