Copy blob to another storage account

Artem Shaturskyi 85 Reputation points
2025-01-14T11:35:03.5766667+00:00

Hello! I'm trying to copy blob from one Azure Storage account to another within Azure Logic App. The blob is large (VHD OS image) so it is not possible to do the copy using the Copy Blob (V2) action. So I'm trying to do that with REST API:

{
    "uri": "https://<target storage account>/<target container>/<target blob>",
    "method": "PUT",
    "headers": {
        "Authorization": "
        "x-ms-date": "Tue, 14 Jan 2025 11:11:50 GMT",
        "x-ms-version": "2014-02-14",
        "Content-Length": "0",
        "x-ms-copy-source": "<Source blob SAS URI>",
        "x-ms-blob-type": "BlockBlob"
    },
    "authentication": {
        "audience": "https://storage.azure.com/",
        "identity": "<Managed Identity>",
        "type": "ManagedServiceIdentity"
    }
}

And whatever I tried I got the error:

<?xml version="1.0" encoding="utf-8"?><Error><Code>AuthenticationFailed</Code><Message>Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.RequestId:1e96bb7c-0000-0000-0000-66e7e2000000Time:2025-01-14T11:11:50.7171818Z</Message><AuthenticationErrorDetail>Authentication scheme Bearer is not supported in this version.</AuthenticationErrorDetail></Error>

What I'm doing wrong? Could you please advise how to implement this copy in Logic App using REST API (without using AzCopy or Function app)?

Azure Blob Storage
Azure Blob Storage
An Azure service that stores unstructured data in the cloud as blobs.
3,047 questions
Azure Logic Apps
Azure Logic Apps
An Azure service that automates the access and use of data across clouds without writing code.
3,322 questions
{count} votes

Accepted answer
  1. Amira Bedhiafi 28,066 Reputation points
    2025-01-14T20:18:54.4866667+00:00

    I think that the authentication mechanism you're using is not correct for the operation you want to perform.

    You are using Managed Service Identity for authentication, but Azure Blob Storage expects the Authorization header to be properly signed with the correct signature and not with a bearer token. The error indicates that the Bearer token method is not supported in this context.

    For the PUT operation to copy the blob, you need to use the correct signature, which involves creating a Shared Access Signature (SAS) for the source blob, or the operation must be authenticated using the appropriate service account key.

    Azure Storage supports copying a blob from one account to another by sending a PUT request to the target blob's URI, along with the x-ms-copy-source header pointing to the source blob's SAS URI. However, this requires a valid SAS token, or it must be done with correct authentication via an account key.

    What is recommended ?

    You must create a SAS token for the source blob, which you will use in the x-ms-copy-source header. The SAS token should allow reading the source blob and should have appropriate permissions ( r for read access).

    Steps to create SAS for the source blob:

    1. Go to the Azure portal.
    2. Navigate to your source storage account and locate the blob.
    3. Generate a SAS token with read access (r) for the blob.

    Example x-ms-copy-source header:

    x-ms-copy-source: https://<source-storage-account>.blob.core.windows.net/<source-container>/<source-blob>?<sas-token>
    

    Since you're using Logic Apps, ensure that the managed identity you are using has the necessary permissions to perform the copy operation. You can configure these permissions at the target storage account (assign a Storage Blob Data Contributor role to the managed identity).

    When using the PUT method to copy the blob, ensure the following headers:

    • x-ms-copy-source: The SAS URL to the source blob.
    • x-ms-date: The current date in GMT.
    • x-ms-version: A valid storage API version (e.g., 2019-02-02).
    • x-ms-blob-type: BlockBlob (or the correct type depending on the blob).
    {
        "uri": "https://<target-storage-account>.blob.core.windows.net/<target-container>/<target-blob>",
        "method": "PUT",
        "headers": {
            "Authorization": "<account-key-or-SAS>",
            "x-ms-date": "Tue, 14 Jan 2025 11:11:50 GMT",
            "x-ms-version": "2019-02-02",
            "Content-Length": "0",
            "x-ms-copy-source": "https://<source-storage-account>.blob.core.windows.net/<source-container>/<source-blob>?<sas-token>",
            "x-ms-blob-type": "BlockBlob"
        },
        "authentication": {
            "audience": "https://storage.azure.com/",
            "identity": "<Managed Identity>",
            "type": "ManagedServiceIdentity"
        }
    }
    
    

    If the REST API approach continues to be troublesome, you can also use the Copy Blob action in Azure Logic Apps. Even though you mentioned you can't use it due to the blob size, you could try breaking the blob into smaller parts or consider other workarounds to manage large files.


1 additional answer

Sort by: Most helpful
  1. Keshavulu Dasari 3,095 Reputation points Microsoft Vendor
    2025-01-24T20:41:52.5966667+00:00

    Hi Artem Shaturskyi,

    Apologies for the delay response!

    To wait for the copy operation to finish, you can use the Get Blob Properties REST API to check the status of the copy operation. You can implement a loop in your Logic App to periodically check the status until it is complete, Initiate the Copy Operation: As you've done already.

    Use the Get Blob Properties API to check the x-ms-copy-status header.

    Loop Until Complete: Repeat the status check until the copy status is success.

    example of how you might structure this in your Logic App:

    {
        "uri": "https://<target storage account>/<target container>/<target blob>",
        "method": "HEAD",
        "headers": {
            "x-ms-date": "<current date>",
            "x-ms-version": "2014-02-14"
        },
        "authentication": {
            "audience": "https://storage.azure.com/",
            "identity": "<Managed Identity>",
            "type": "ManagedServiceIdentity"
        }
    }
    

    You can use a Until loop in your Logic App to keep checking the status until it is success.

    Generating a SAS Token Using REST API in Logic App

    You can generate a SAS token using the REST API, but it typically involves using an Azure Function to handle the token generation.

    Create an Azure Function: This function will generate the SAS token.

    Call the Function from Logic App: Use an HTTP action in your Logic App to call the Azure Function and get the SAS token.

    example of how you might set up the Azure Function:

    # PowerShell script to generate SAS token
    param($accountName, $accountKey, $containerName, $blobName)
    
    $context = New-AzStorageContext -StorageAccountName $accountName -StorageAccountKey $accountKey
    $policy = New-AzStorageBlobSASTokenPolicy -Permission r -ExpiryTime (Get-Date).AddHours(1) -IPAddressOrRange "0.0.0.0-255.255.255.255"
    $sasToken = New-AzStorageBlobSASToken -Context $context -Container $containerName -Blob $blobName -Policy $policy
    
    $sasToken
    

    You can then call this function from your Logic App and use the returned SAS token.

    Final Setup

    For your final setup, you can integrate these steps into your Logic App workflow:

    Create VM Snapshot: Already done & Copy VHD Image: Already done.

    Generate SAS Token: Use the Azure Function to generate the SAS token with the allowed IP range.


    Please do not forget to "Accept the answer” and “up-vote” wherever the information provided helps you, this can be beneficial to other community members.           

    If you have any other questions or are still running into more issues, let me know in the "comments" and I would be happy to help you

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.