Search code examples
azure-blob-storageazure-storageazure-rbac

Getting error when copying file from one container to another container in Azure Storage using .Net client library


I am trying to copy a file from one storage account container to another storage account container. Both accounts are public. I am using Microsoft Managed account (Role based access accoount)and I am the owner. From my machine as an admin. I am able to perform upload, download and get the list from both container. but when I perform copy. I get the below error. See the below code and then the error.

var targetContainer = "targetContainer";  
var targetStorageAccount = "targetStorage";
var targetUrlurl2 = @"https://" + targetStorageAccount + ".blob.core.windows.net";
  var targetServiceClient = new BlobServiceClient(
           new Uri(targetUrlurl2),
       new DefaultAzureCredential());



        var stageStorageAccount = "sourceStorage"; 
        var stageContainer = "sourceContainer";

        var stageUrl = @"https://" + stageStorageAccount + ".blob.core.windows.net";
        var stageServiceClient = new BlobServiceClient(
           new Uri(stageUrl),
       new DefaultAzureCredential());


        BlobContainerClient stageContainerClient = stageServiceClient.GetBlobContainerClient(stageContainer);
        var list = stageContainerClient.GetBlobs();  
        BlobContainerClient targetContainerClient = targetServiceClient.GetBlobContainerClient(targetContainer);
        BlobClient sourceBlobClient = stageContainerClient.GetBlobClient(fileName);
        BlobClient targetBlobClient = targetContainerClient.GetBlobClient(fileName);

        var result = targetBlobClient.StartCopyFromUri(sourceBlobClient.Uri);

Error

Server failed to authenticate the request. Please refer to the information in the www- 
authenticate header.
RequestId:c9a58588-301e-0062-1686-9d067c000000
 Time:2023-06-12T23:32:17.2971373Z
 Status: 401 (Server failed to authenticate the request. Please refer to the information in 
 the www-authenticate header.)
 ErrorCode: CannotVerifyCopySource

 CannotVerifyCopySource Server failed to authenticate the request. Please refer to the information in the www-authenticate header. RequestId:c9a58588-301e-0062-1686-9d067c000000 Time:2023-06-12T23:32:17.2971373Z

 Headers:
 x-ms-request-id: c9a58588-301e-0062-1686-9d067c000000
  x-ms-client-request-id: 4ee3654d-3c1f-44d2-bd87-66297ef299e1
 x-ms-version: 2022-11-02
 x-ms-error-code: CannotVerifyCopySource
 Content-Length: 297
 Content-Type: application/xml
  Date: Mon, 12 Jun 2023 23:32:17 GMT
  Server: Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0

Solution

  • To fix this issue, please use a SAS URL with at least read permission for the source blob.

    For copy operation across storage accounts to work, source blob must be publicly accessible somehow (SAS URL is one way to do it) so that it can be read by storage service when performing copy operation.

    UPDATE

    Please take a look at the code below to see how you can create a User Delegation SAS on the source blob.

    DateTimeOffset expiryTime = DateTimeOffset.UtcNow.AddMinutes(5);
    var userDelegationKey = await stageServiceClient.GetUserDelegationKeyAsync(null, expiryTime, CancellationToken.None);
    var sasBuilder = new BlobSasBuilder()
    {
        BlobContainerName = containerName,
        BlobName = blobName,
        Resource = "b",
        ExpiresOn = linkExpiry
    };
    sasBuilder.SetPermissions(BlobSasPermissions.Read);
    var blobClient = stageContainerClient.GetBlobClient(fileName);
    var blobUriBuilder = new BlobUriBuilder(blobClient.Uri)
    {
        Sas = sasBuilder.ToSasQueryParameters(userDelegationKey,
            stageServiceClient.AccountName)
    };
    return blobUriBuilder.ToUri();