Search code examples
phpazureapicontainersblob

How to create container azure storage using PHP CURL pre requested code


<?php
$accesskey = "{accesskey}";
$storageAccount = '{accountname}';
$destinationURL = "https://$storageAccount.blob.core.windows.net/{accountname}?restype=container";
function createContainer($storageAccount, $accesskey, $destinationURL)
{
    $currentDate = gmdate("D, d M Y H:i:s T", time());
    $headerResource = "x-ms-date:$currentDate\nx-ms-version:2015-12-11\nx-ms-default-encryption-scope:$accesskey\nx-ms-deny-encryption-scope-override:2015-12-11\nx-ms-meta-Name: StorageSample";
    $arraysign = array();
    $arraysign[] = 'PUT';
    $arraysign[] = '';
    $arraysign[] = '';
    $arraysign[] = '';
    $arraysign[] = '';
    $arraysign[] = 'application/json';
    $arraysign[] = '';
    $arraysign[] = '';
    $arraysign[] = '';
    $arraysign[] = '';
    $arraysign[] = '';
    $arraysign[] = '';
    $arraysign[] = $headerResource;
    $str2sign = implode("\n", $arraysign);
    $sig = base64_encode(hash_hmac('sha256', urldecode(utf8_encode($str2sign)) , base64_decode($accesskey) , true));
    $authHeader = "SharedKey $storageAccount:$sig";
    $headers = ['Authorization: ' . $authHeader, 'x-ms-date: ' . $currentDate, 'x-ms-version: 2015-12-11', 'Content-Type: application/json', 'x-ms-meta-Name: StorageSample', 'Content-Length:1024', 'x-ms-default-encryption-scope:' . $accesskey, 'x-ms-deny-encryption-scope-override: true'];
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $destinationURL);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");
    $result = curl_exec($ch);
    echo "<pre>";
    print_r($result);
    echo curl_error($ch);
    curl_close($ch);
}
createContainer($storageAccount, $accesskey, $destinationURL);

?>

Getting following error

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


Solution

  • If you want to use the request headers x-ms-default-encryption-scope and x-ms-deny-encryption-scope-override when we create an Azure blob container, the x-ms-version should be later that 2019-02-02.

    enter image description here

    Besides, when we create the shared key, the formate of signature string should be like

    StringToSign = VERB + "\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 + "\n" +  
                   CanonicalizedHeaders +   
                   CanonicalizedResource;  
    

    But you do not specify CanonicalizedResource in your code. Please set it.

    For example

    $currentDate = gmdate("D, d M Y H:i:s T", time());
        $storageAccount="qsstorageacc";
        $containerName="mytest";
        $accesskey="";
        $encryptionScope="test";
        $currentDate = gmdate("D, d M Y H:i:s T", time());
        print $currentDate;
        print "\n";
        $headerResource = "x-ms-date:$currentDate\nx-ms-default-encryption-scope:$encryptionScope\nx-ms-deny-encryption-scope-override:true\nx-ms-meta-name:mytest\nx-ms-version:2020-04-08";
        $urlResource = "/$storageAccount/$containerName\nrestype:container";
    
        $arraysign = array();
        $arraysign[] = 'PUT';               /*HTTP Verb*/  
        $arraysign[] = '';                  /*Content-Encoding*/  
        $arraysign[] = '';                  /*Content-Language*/  
        $arraysign[] = '';                  /*Content-Length (include value when zero)*/  
        $arraysign[] = '';                  /*Content-MD5*/  
        $arraysign[] = '';                  /*Content-Type*/  
        $arraysign[] = '';                  /*Date*/  
        $arraysign[] = '';                  /*If-Modified-Since */  
        $arraysign[] = '';                  /*If-Match*/  
        $arraysign[] = '';                  /*If-None-Match*/  
        $arraysign[] = '';                  /*If-Unmodified-Since*/  
        $arraysign[] = '';                  /*Range*/  
        $arraysign[] = $headerResource;     /*CanonicalizedHeaders*/
        $arraysign[] = $urlResource;        /*CanonicalizedResource*/
    
        $str2sign = implode("\n", $arraysign);
        print $str2sign;
        print "\n";
    
        $sig = base64_encode(hash_hmac('sha256', urldecode(utf8_encode($str2sign)), base64_decode($accesskey), true));  
        $authHeader = "SharedKey $storageAccount:$sig";
        print $authHeader;
        print "\n";
    
        $headers = [
            'Authorization: ' . $authHeader,
            'x-ms-deny-encryption-scope-override: true',
            'x-ms-date: ' . $currentDate,
            'x-ms-default-encryption-scope: ' . $encryptionScope,
            'x-ms-version: 2020-04-08',
            'x-ms-meta-name: mytest',
            'Content-Length: 0'
        ];
        print_r($headers);
        $destinationURL="https://qsstorageacc.blob.core.windows.net/mytest?restype=container";
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $destinationURL);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");
        $result = curl_exec($ch);
        echo "<pre>";
        print_r($result);
        echo curl_error($ch);
        curl_close($ch);
    

    enter image description here

    For more details, please refer to

    https://learn.microsoft.com/en-us/rest/api/storageservices/authorize-with-shared-key

    https://learn.microsoft.com/en-us/rest/api/storageservices/create-container