Search code examples
azureazure-active-directoryqueuestorageidentity

How to use Azure.Identity.ClientSecretCredential to access a Azure Queue?


I've created an App Registration in Azure and added access to Azure Storage (user_impersonation): enter image description here

The console app uses these packages:

<PackageReference Include="Azure.Identity" Version="1.2.0-preview.6" />
<PackageReference Include="Azure.Storage.Queues" Version="12.4.0-preview.5" />

And the code looks like:

var tc = new ClientSecretCredential("{tenant-id}", "{client-id}", "{client-secret}");
var client = new QueueClient(new Uri("https://{storage-name}.queue.core.windows.net/example-q"), tc);

// this fails with error
client.SendMessage("msg");

The error message is like:

Unhandled exception. Azure.RequestFailedException: This request is not authorized to perform this operation using this permission.
RequestId:13f45216-9003-0061-49cf-616632000000
Time:2020-07-24T15:32:44.9586872Z
Status: 403 (This request is not authorized to perform this operation using this permission.)
ErrorCode: AuthorizationPermissionMismatch

Headers:
Server: Windows-Azure-Queue/1.0,Microsoft-HTTPAPI/2.0
x-ms-request-id: 13f45216-9003-0061-49cf-616632000000
x-ms-version: 2018-11-09
x-ms-error-code: AuthorizationPermissionMismatch
Date: Fri, 24 Jul 2020 15:32:44 GMT
Content-Length: 279
Content-Type: application/xml

   at Azure.Storage.Queues.QueueRestClient.Messages.EnqueueAsync_CreateResponse(ClientDiagnostics clientDiagnostics, Response response)
   at Azure.Storage.Queues.QueueRestClient.Messages.EnqueueAsync(ClientDiagnostics clientDiagnostics, HttpPipeline pipeline, Uri resourceUri, QueueSendMessage message, String version, Nullable`1 visibilitytimeout, Nullable`1 messageTimeToLive, Nullable`1 timeout, String requestId, Boolean async, String operationName, CancellationToken cancellationToken)
   at Azure.Storage.Queues.QueueClient.SendMessageInternal(String messageText, Nullable`1 visibilityTimeout, Nullable`1 timeToLive, Boolean async, CancellationToken cancellationToken)
   at Azure.Core.Pipeline.TaskExtensions.EnsureCompleted[T](Task`1 task)
   at Azure.Storage.Queues.QueueClient.SendMessage(String messageText, Nullable`1 visibilityTimeout, Nullable`1 timeToLive, CancellationToken cancellationToken)
   at Azure.Storage.Queues.QueueClient.SendMessage(String messageText)

Solution

  • If you want to use service principal to access Azure queue storage, you must assign Azure RABC role (Storage Queue Data Contributor) to the sp. For more details, please refer to the document

    For example

    1. Create service principal and assign role
    az login
    
    az ad sp create-for-rbac -n "MyApp" --role 'Storage Queue Data Contributor' \
      --scope '/subscriptions/<subscription>/resourceGroups/<resource-group>/providers/Microsoft.Storage/storageAccounts/<storage-account>'
    
    1. Code (I use the same version sdk)
    ClientSecretCredential cred = new ClientSecretCredential(tenantId, clientId, clientSecret);
    var client = new QueueClient(new Uri("https://blobstorage0516.queue.core.windows.net/test"), cred);
    string message = "First Message to azure Queue";
    client.SendMessage(message);
    

    enter image description here