使用用户分配的托管标识进行Azure服务总线身份验证

使用用户分配的托管标识进行Azure服务总线身份验证,azure,azure-active-directory,azureservicebus,azure-managed-identity,Azure,Azure Active Directory,Azureservicebus,Azure Managed Identity,我们需要从Azure应用程序服务和Azure功能运行访问Azure服务总线ASB的应用程序。我们需要使用用户指定的身份进行身份验证。我们编写以下代码,用于系统分配的标识,但不用于用户分配的标识: var tokenProvider = TokenProvider.CreateManagedIdentityTokenProvider(); var managementClient = new ManagementClient(serviceBusEndpoint, tokenProvider);

我们需要从Azure应用程序服务和Azure功能运行访问Azure服务总线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)
因此,找不到指定ClientId/ResourceId的MSI的核心错误。。看起来我们需要指定客户端id。然后我们找到了ManagedIdentityCredential,可以在其中指定客户端id,但还没有找到如何将其用于ASB


另一个选项是使用HTTP GET请求到MSI_端点,如这里所述,但可能是真正的工作.net库存在,我们错过了。

我是Azure SDK团队的成员。我们正在这里统一所有Azure SDK,但还没有新的服务总线SDK

我没有尝试使用TokenProvider API使用用户分配的身份,但我知道它与新的DefaultAzureCredential对象一起工作,该对象将在您的环境中搜索Cred,并自动拾取托管身份端点。您可以在此处阅读更多信息:

但是,您不能直接使用DefaultAzureCredential,因为ServiceBus接受ITokenProvider

同时,您可以使用我创建的这个适配器——这只是权宜之计,直到我们有了服务总线SDK

将Azure.Identity和Azure.Core nuget包添加到项目中

将此文件复制到您的项目:

下面是一个示例用法

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

AZURE_CLIENT_ID

AZURE_CLIENT_SECRET

AZURE_TENANT_ID

如果您必须使用TokenProvider并且不想使用权宜之计,请让我知道,我可以进一步研究。

我是Azure SDK团队的成员。我们正在这里统一所有Azure SDK,但还没有新的服务总线SDK

我没有尝试使用TokenProvider API使用用户分配的身份,但我知道它与新的DefaultAzureCredential对象一起工作,该对象将在您的环境中搜索Cred,并自动拾取托管身份端点。您可以在此处阅读更多信息:

但是,您不能直接使用DefaultAzureCredential,因为ServiceBus接受ITokenProvider

同时,您可以使用我创建的这个适配器——这只是权宜之计,直到我们有了服务总线SDK

将Azure.Identity和Azure.Core nuget包添加到项目中

将此文件复制到您的项目:

下面是一个示例用法

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

AZURE_CLIENT_ID

AZURE_CLIENT_SECRET

AZURE_TENANT_ID

如果您必须使用TokenProvider并且不想使用权宜之计,请告诉我,我可以进一步研究。

TokenProvider.CreateManagedEntityTokenProvider依赖于实现托管标识

Microsoft.Azure.Services.AppAuthentication的1.2.1版支持用户分配的托管标识。可以找到文档

因此,您必须做两件事才能使用现有的代码实现此功能:

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

2.将AppService的应用设置中的AzureServicesAuthConnectionString设置为RunAs=App;AppId={ClientId of user assigned identity}。e、 g.RunAs=App;AppId=587f16c8-81ed-41c7-b19a-9ded0dbe2ca2


完成这两个步骤后,代码应该使用用户分配的托管标识。我在一个应用程序服务上试用过,效果很好

TokenProvider.CreateManagedEntityTokenProvider依赖于实现托管标识

Microsoft.Azure.Services.AppAuthentication的1.2.1版支持用户分配的托管标识。可以找到文档

因此,您必须做两件事才能使用现有的代码实现此功能:

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

2.将AppService的应用设置中的AzureServicesAuthConnectionString设置为RunAs=App;AppId={ClientId of user assigned identity}。e、 g.RunAs=App;AppId=587f16c8-81ed-41c7-b19a-9ded0dbe2ca2


完成这两个步骤后,代码应该使用用户分配的托管标识。我在一个应用程序服务上试用过,效果很好

从今天起,我们可以让用户指定使用以下代码

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

它与https://servicebus.azure.net/.default 同样如此。

从今天起,我们可以让用户指定使用以下代码

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

它与https://servicebus.azure.net/.default 同样。

IIRC为用户分配的MSI获取令牌需要知道并提供您想要令牌的MSI的GUID。这是否发生了变化,或者DefaultAzureCredential是否以某种方式处理了此问题?我更新了答案,以包含用户分配所需的环境变量。谢谢。谢谢,@JonGallant我们会试试这个并标记你的po
st作为答案。@Alezis-请参阅下面Varun的答案,了解目前官方支持的解决方法。@JonGallant感谢您的帮助!我们没有尝试您的方法,因为它看起来像是通过服务主体通过指定clientid/secret进行身份验证,但Varun的答案是有效的。它也可以通过ManagedIdentityCredential类工作。IIRC为用户分配的MSI获取令牌需要知道并提供要为其提供令牌的MSI的GUID。这是否发生了变化,或者DefaultAzureCredential是否以某种方式处理了此问题?我更新了答案,以包含用户分配所需的环境变量。谢谢。谢谢,@JonGallant我们将尝试此方法,并将您的帖子标记为答案。@Alezis-请参阅下面Varun的答案,了解当前官方支持的方法。@JonGallant感谢您的帮助!我们没有尝试您的方法,因为它看起来像是通过服务主体通过指定clientid/secret进行身份验证,但Varun的答案是有效的。它也通过ManagedIdentityCredential类工作。是的,它工作。我在Microsoft.Azure.ServiceBus 4.1.1中使用了此方法,该方法引用了旧的Microsoft.Azure.Services.AppAuthentication 1.0.3,该方法不适用于用户分配。更新到Microsoft.Azure.Services.AppAuthentication1.2.1修复了此问题。但是,我已经使用Azure中的新ManagedIdentityCredential类实现了aut。根据它支持的这个页面,标识也可以实现。@Varun,你确定AzureServicesAuthConnectionString可以作为应用程序设置使用吗?如果是,如何和在哪里?我可以让它作为一个环境变量工作,或者手动注入它:new AzureServiceTokenProviderRunAs=。。。。然而,作为一个应用程序设置,它似乎被忽略了。是的,它可以工作。我在Microsoft.Azure.ServiceBus 4.1.1中使用了此方法,该方法引用了旧的Microsoft.Azure.Services.AppAuthentication 1.0.3,该方法不适用于用户分配。更新到Microsoft.Azure.Services.AppAuthentication1.2.1修复了此问题。但是,我已经使用Azure中的新ManagedIdentityCredential类实现了aut。根据它支持的这个页面,标识也可以实现。@Varun,你确定AzureServicesAuthConnectionString可以作为应用程序设置使用吗?如果是,如何和在哪里?我可以让它作为一个环境变量工作,或者手动注入它:new AzureServiceTokenProviderRunAs=。。。。然而,作为应用程序设置,它似乎被忽略了。