Home > Software engineering >  Authorization of Azure Storage service REST API for Next.js with Node.js server - Copy Blob From URL
Authorization of Azure Storage service REST API for Next.js with Node.js server - Copy Blob From URL

Time:10-28

Reference1: https://docs.microsoft.com/en-us/rest/api/storageservices/copy-blob-from-url

Reference2: Authorization of Azure Storage service REST API

I implemented listing of containers according to the above reference2 as a backend server in Next.js (/pages/api/). I got the implementation in Reference2 to work with response status===OK. My goal is to copy a blob with tier===cool and paste it into a different container with tier===archive so I don't have to change the archived blob's access tier when downloading it.

I follow exactly reference2 with the following changes:

  1. set strToSign to (least sure about this part):

const strToSign= PUT\n\n\n\n\n\n\n\n\n\n\n\nx-ms-date:${strTime}\nx-ms-version:2020-10-02\n/${account}/\n${containerName}/${blobName}

  1. set header (following reference1) to:

     const putConfig = {
         method: 'PUT', 
         headers: {
             'Authorization': auth,
             'x-ms-date': strTime,
             'x-ms-version': "2020-10-02",
             'x-ms-copy-source': blobUrl,
             'x-ms-requires-sync':'true'
         }
    

    }

where (as in reference1),

   const blobUrl = `https://${account}.blob.core.windows.net/${containerName}/${blobName}`
  1. The fetch is set up like this:

    fetch(https://${account}.blob.core.windows.net/${containerName}/${blobName}, putConfig) .then( results => console.log(results), res.end())

  2. This is the console.log(results) output I get:

    Response { size: 0, timeout: 0, [Symbol(Body internals)]: { body: PassThrough { _readableState: [ReadableState], _events: [Object: null prototype], _eventsCount: 2, _maxListeners: undefined, _writableState: [WritableState], allowHalfOpen: true, [Symbol(kCapture)]: false, [Symbol(kCallback)]: null }, disturbed: false, error: null }, [Symbol(Response internals)]: { url: 'https://.blob.core.windows.net//', status: 403, statusText: 'Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.', headers: Headers { [Symbol(map)]: [Object: null prototype] }, counter: 0 } }

Not sure what the error is - can it be related to setting access on the specific blob (resource) on azure portal? How do you fix this issue?

P.S.

Reference3: Authentication Failed in REST api call to PUT Blob in Azure Storage [REST][Azure Blob]

I also tried to use the following:

const strToSign = `PUT\n\n\n\n\n\n\n\n\n\n\n\nx-ms-blob-type:BlockBlob\nx-ms-date:${strTime}\nx-ms-version:2020-10-02\n/${account}/\n${containerName}/\n${blobName}`;

The error remains the same.

CodePudding user response:

As Suggested By Gaurav Matri

blob is in the archive access tier, it's considered to be offline and can't be read or modified.

In order to read or modify data in an archived blob, you must first rehydrate the blob to an online tier, either the hot or cool tier.

There are two options for rehydrating a blob that is stored in the archive tier:

  1. Copy an archived blob to an online tier

You can rehydrate an archived blob by copying it to a new blob in the hot or cool tier with the Copy Blob or Copy Blob from URL operation. Microsoft recommends this option for most scenarios.

  1. Change a blob's access tier to an online tier

You can rehydrate an archived blob to hot or cool by changing its tier using the Set Blob Tier operation.

For more details refer this document

CodePudding user response:

SOLUTION:

const CryptoJS = require("crypto-js");

const key = "accesskey";
const version="2020-10-02"
const account = 'storagename'
const containerName = 'containername'
const strTime = (new Date()).toUTCString();

export default async (req, res) => {  
  if (req.method === 'POST') {

    const { blobName } = req.body
    const srcBlobName = blobName
    const srcBlobUrl = `https://${account}.blob.core.windows.net/${containerName}/${srcBlobName}`
    const destBlobName = srcBlobName   'rHrH'
    const destBlobUrl = `https://${account}.blob.core.windows.net/${containerName}/${destBlobName}`;
    
    const destAccessTier = 'Cool'
    const canonicalizedHeaders = `x-ms-access-tier:${destAccessTier}\nx-ms-copy-source:${srcBlobUrl}\nx-ms-date:${strTime}\nx-ms-version:${version}\n`;
    const canonicalizedResource = `/${account}/${containerName}/${destBlobName}`;
    const strToSign = `PUT\n\n\n\n\n\n\n\n\n\n\n\n${canonicalizedHeaders}${canonicalizedResource}`;
    const secret = CryptoJS.enc.Base64.parse(key);
    const hash = CryptoJS.HmacSHA256(strToSign, secret);
    const hashInBase64 = CryptoJS.enc.Base64.stringify(hash);
    const auth = `SharedKey ${account}:` hashInBase64;
    
    const PUTconfig = {
    method: 'PUT',
    headers: {
        'x-ms-access-tier': destAccessTier,
        'x-ms-copy-source': srcBlobUrl,
        'x-ms-date': strTime,
        'x-ms-version': version,
        'Authorization': auth
        }
    };

    fetch(destBlobUrl, PUTconfig)
    .then( results => {
        if(results.status==200) {console.log('api works')} else {console.log(results)}},
        res.end()
    )    
  } 
}
  • Related