用户分配的托管身份的Azure Service Bus身份验证

时间:2020-02-24 18:10:31

标签: azure azure-active-directory azureservicebus azure-managed-identity

我们需要从Azure App Services和Azure Functions访问Azure Service Bus(ASB)的运行应用程序。我们需要使用用户分配的身份进行身份验证。我们编写以下代码,这些代码适用于系统分配的身份,但不适用于用户分配的身份:

var tokenProvider = TokenProvider.CreateManagedIdentityTokenProvider();
var managementClient = new ManagementClient(serviceBusEndpoint, tokenProvider);

if(await managementClient.QueueExistsAsync(queueName))
{
    return new OkObjectResult($"Queue with name {queueName} exists.");
}
else
{
    return new OkObjectResult($"Queue with name {queueName} doesn't exist.");
}

抛出此错误:

Microsoft.Azure.Services.AppAuthentication.AzureServiceTokenProviderException: Parameters: Connection String: [No connection string specified], Resource: https://servicebus.azure.net/, Authority: . Exception Message: Tried the following 3 methods to get an access token, but none of them worked.
Parameters: Connection String: [No connection string specified], Resource: https://servicebus.azure.net/, Authority: . Exception Message: Tried to get token using Managed Service Identity. Access token could not be acquired. MSI ResponseCode: BadRequest, Response: {"StatusCode":400,"Message":"No MSI found for specified ClientId/ResourceId.","CorrelationId":"dd2bcf6c-6f1d-489e-b178-ca6007502841"}
Parameters: Connection String: [No connection string specified], Resource: https://servicebus.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"
Parameters: Connection String: [No connection string specified], Resource: https://servicebus.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,
operable program or batch file.


   at Microsoft.Azure.Services.AppAuthentication.AzureServiceTokenProvider.GetAccessTokenAsyncImpl(String authority, String resource, String scope)
   at Microsoft.Azure.Services.AppAuthentication.AzureServiceTokenProvider.GetAccessTokenAsync(String resource, String tenantId)
   at Microsoft.Azure.ServiceBus.Primitives.ManagedIdentityTokenProvider.GetTokenAsync(String appliesTo, TimeSpan timeout)
   at Microsoft.Azure.ServiceBus.Management.ManagementClient.GetToken(String requestUri)
   at Microsoft.Azure.ServiceBus.Management.ManagementClient.SendHttpRequest(HttpRequestMessage request, CancellationToken cancellationToken)
   at Microsoft.Azure.ServiceBus.Management.ManagementClient.GetEntity(String path, String query, Boolean enrich, CancellationToken cancellationToken)
   at Microsoft.Azure.ServiceBus.Management.ManagementClient.GetQueueAsync(String queuePath, CancellationToken cancellationToken)
   at Microsoft.Azure.ServiceBus.Management.ManagementClient.QueueExistsAsync(String queuePath, CancellationToken cancellationToken)

所以核心错误是No MSI found for specified ClientId/ResourceId.。看起来我们需要指定客户端ID。然后,我们发现https://github.com/Azure/azure-sdk-for-net/tree/master/sdk/identity/Azure.IdentityManagedIdentityCredential可以在其中指定客户端ID,但尚未弄清楚如何将其用于ASB。

其他选项正在使用对MSI_ENDPOINT的HTTP GET请求,如此处https://docs.microsoft.com/en-us/azure/app-service/overview-managed-identity?context=azure%2Factive-directory%2Fmanaged-identities-azure-resources%2Fcontext%2Fmsi-context&tabs=dotnet#obtaining-tokens-for-azure-resources所述,但可能是我们错过的真实的.net库。

3 个答案:

答案 0 :(得分:3)

我在Azure SDK团队中。我们正在https://aka.ms/azsdkpackages处统一所有Azure SDK,但还没有新的Service Bus SDK。

我还没有尝试使用TokenProvider API进行用户分配的身份,但是我知道它可以与新的DefaultAzureCredential对象一起使用,该对象将在您的环境中搜索凭据,并自动获取Managed Identity端点。您可以在这里了解更多信息:https://docs.microsoft.com/en-us/dotnet/api/azure.identity.defaultazurecredential?view=azure-dotnet

但是,由于ServiceBus接受ITokenProvider,因此不能直接使用DefaultAzureCredential。

同时,您可以使用我创建的此适配器-在我们拥有Service Bus SDK之前,这只是权宜之计。

  1. 将Azure.Identity和Azure.Core nuget程序包添加到您的项目中。

  2. 将此文件复制到您的项目中: https://github.com/jongio/azidext/blob/master/net/JonGallant.Azure.Identity.Extensions/DefaultAzureServiceBusCredential.cs

  3. 这是一个示例用法 https://github.com/jongio/azidext/blob/master/net/JonGallant.Azure.Identity.Extensions.Tests/ServiceBus/ServiceBusTests.cs

您可以使用以下环境变量设置客户端ID,机密和租户ID:

AZURE_CLIENT_ID

AZURE_CLIENT_SECRET

AZURE_TENANT_ID

如果您必须使用TokenProvider而又不想使用权宜之计,请告诉我,我可以对其进行进一步研究。

答案 1 :(得分:2)

TokenProvider.CreateManagedIdentityTokenProvider依赖于Microsoft.Azure.Services.AppAuthentication来实现托管身份。

Microsoft.Azure.Services.AppAuthentication的1.2.1版支持用户分配的受管身份。可以找到文档here

因此,您必须做两件事,以使其与已经拥有的代码一起使用:

1。将Microsoft.Azure.Services.AppAuthentication的版本更新为最新版本

2。在AppService的App设置中将 AzureServicesAuthConnectionString 设置为RunAs = App; AppId = {用户分配的身份的ClientId}。例如RunAs = App; AppId = 587f16c8-81ed-41c7-b19a-9ded0dbe2ca2

完成这两个步骤后,您的代码应使用用户分配的托管身份。我通过应用服务对其进行了尝试,对我来说效果很好。

答案 2 :(得分:0)

截止到今天,我们可以为用户分配以下代码。

var managedCredential = new ManagedIdentityCredential(userAssignedIdentityAppId);
var accessToken = await _managedCredential.GetTokenAsync(
                        new TokenRequestContext(
                            new[] { "https://servicebus.azure.net" })).ConfigureAwait(false);

它也可以与"https://servicebus.azure.net/.default"一起使用。