Home > OS >  Getting Azure Blob properties via REST
Getting Azure Blob properties via REST

Time:01-06

Given an azure account (myAccount) and a container (myContainer), which holds a folder (2022-12-01) and a zip file (myFile.zip) in it. I'm trying to get the x-ms-copy-status property of the above mentioned file in the container. According to the the documentation, it can be done via a REST call, so I'm using Postman to create the call (also tried with a simple console app, but got the same results).

In my understanding I need to provide at least 3 headers: Authorization, Date (x-ms-date) and x-ms-version. Found a great example how to construct a pre-request script here. My version looks like this:

const key = "...";

pm.environment.set("dateHeader", new Date().toUTCString());

const strToSign = 'HEAD\n\n\n\nx-ms-date:'   pm.environment.get("dateHeader")   '\nx-ms-version:2015-02-21\n/myAccount/myContainer/2022-12-01/myFile.zip';
const secret = CryptoJS.enc.Base64.parse(key);
const hash = CryptoJS.HmacSHA256(strToSign, secret);
const encoded = CryptoJS.enc.Base64.stringify(hash);

pm.environment.set("authSig", "SharedKeyLite myAccount:"   encoded);

The problem is, I get either an

OutOfRangeInput - One of the request inputs is out of range.

or

AuthenticationFailed - Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.

The second one is more verbose, was able to fix it, but with the first one, I'm out of clues.

Maybe I'm on a wrong path, but the goal would be to find out the given blob has finished copying (has the x-ms-copy-status: success property or any other property indicates the completition).

Update

Request strToSign:

const strToSign = 'HEAD\n\n\n\nx-ms-date:'   pm.environment.get("dateHeader")   '\nx-ms-version:2015-02-21\n/myAccoount/myContainer/2022-12-01/myFile.zip';

Response:

<?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:...
Time:2023-01-05T14:51:29.8834005Z</Message>
    <AuthenticationErrorDetail>The MAC signature found in the HTTP request '...' is not the same as any computed signature. Server used following string to sign: 'GET



x-ms-date:Thu, 05 Jan 2023 14:51:35 GMT
x-ms-version:2015-02-21
/myAccount/'.</AuthenticationErrorDetail>
</Error>

CodePudding user response:

I tried in my environment and got below results:

You can use the below code C# for creating Authorization, Date (x-ms-date) and x-ms-version.

Code:

using System.Globalization;
using System.Net;
using System.Security.Cryptography;

class Program
{
    static void Main(string[] args)
    {
        Blobs();
        Console.WriteLine("done");
        Console.ReadLine();
    }

    static void Blobs()
    {
        string Account = "venkat123";
        string Key = "<storage account key>";
        string Container = "test";
        string blob = "file.json";
        string apiversion = "2021-06-08";

        DateTime dt = DateTime.UtcNow;
        string StringToSign = String.Format("HEAD\n"
              "\n" // content encoding
              "\n" // content language
              "\n" // content length
              "\n" // content md5
              "\n" // content type
              "\n" // date
              "\n" // if modified since
              "\n" // if match
              "\n" // if none match
              "\n" // if unmodified since
              "\n" // range
              "x-ms-date:"   dt.ToString("R")   "\nx-ms-version:"   apiversion   "\n" // headers
              "/{0}/{1}/{2}", Account, Container,blob);

        string auth = SignThis(StringToSign, Key, Account);

        Console.WriteLine($"the date is: {dt.ToString("R")}");
        Console.WriteLine($"the auth token is: {auth}");
        Console.WriteLine("*********");
        string method = "HEAD";
        string urlPath = string.Format("https://{0}.blob.core.windows.net/{1}/{2}", Account, Container,blob);
        Uri uri = new Uri(urlPath);
        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
        request.Method = method;
        request.Headers.Add("x-ms-date", dt.ToString("R"));
        request.Headers.Add("x-ms-version", apiversion);
        request.Headers.Add("Authorization", auth);

        Console.WriteLine("***Get blob properties ***");
        using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
        {

            using (StreamReader reader = new StreamReader(response.GetResponseStream()))
            {
                Console.WriteLine(reader.ReadToEnd());
            }
        }
    }


    private static String SignThis(String StringToSign, string Key, string Account)
    {
        String signature = string.Empty;
        byte[] unicodeKey = Convert.FromBase64String(Key);
        using (HMACSHA256 hmacSha256 = new HMACSHA256(unicodeKey))
        {
            Byte[] dataToHmac = System.Text.Encoding.UTF8.GetBytes(StringToSign);
            signature = Convert.ToBase64String(hmacSha256.ComputeHash(dataToHmac));
        }

        String authorizationHeader = String.Format(
              CultureInfo.InvariantCulture,
              "{0} {1}:{2}",
              "SharedKey",
              Account,
              signature);

        return authorizationHeader;
    }
}

Console: enter image description here

Above executed code, date and signature which I copied and used in postman, and it executed header with successfully.

Postman:

enter image description here

Reference: Get Blob Properties (REST API) - Azure Storage | Microsoft Learn.

  • Related