Search code examples
azureazure-storageazure-powershellazure-rest-api

How to Set Directory Metadata in Azure File Share directory


I am trying to Set the meta deta of a directory in Azure File share using Powershell. Rest API Documentation is https://learn.microsoft.com/en-us/rest/api/storageservices/set-directory-metadata If I remove the x-ms-meta-name:value from below code then it works and it deletes the existing metadata but when I try to add it. it gives an authentication error. Error is mentioned at the end of post. Below is the script

$Version = "2017-04-17"
$AccessKey = 'xxxxx'
$storageAccount = 'xxxxx'
$ShareName = 'test'
$Directory = 'testdir'

$date = [System.DateTime]::UtcNow.ToString("R",[Globalization.CultureInfo]::InvariantCulture)

$stringToSign = "PUT`n`n`n`n`n`n`n`n`n`n`n`n"+
           "x-ms-date:$date`nx-ms-version:$version`n" + "x-ms-meta-name:value`n" +
           "/$storageAccount/$ShareName/$Directory`ncomp:metadata`nrestype:directory" 
$hmacsha = New-Object System.Security.Cryptography.HMACSHA256
$hmacsha.key = [Convert]::FromBase64String($accesskey)
$signature = $hmacsha.ComputeHash([Text.Encoding]::UTF8.GetBytes($stringToSign))
$signature = [Convert]::ToBase64String($signature)

$headers=@{"x-ms-date"=$date;
           "x-ms-version"= $version;
           "Authorization"= "SharedKey $($storageAccount):$signature";
           "x-ms-meta-name"= "value"
           
                      
}
$URI = "https://$storageAccount.file.core.windows.net/$($ShareName)/$($Directory)?restype=directory&comp=metadata"

Invoke-WebRequest $URI -Method 'Put' -Headers $headers -UseBasicParsing

Below is the error

Invoke-WebRequest : AuthenticationFailedServer failed to authenticate the 
request. Make sure the value of Authorization header is formed correctly 
including the signature.
RequestId:2b0f9122-601a-00a9-4c0d-0e6c51000000
Time:2022-01-20T14:55:56.8906064ZThe MAC signature found in the HTTP request 
'Q1HSohGOPCL5uR2WuFqpn/Ix8ZgEBqXF8EjXC4Jd4rs=' is not the same as any computed 
signature. Server used following string to sign: 'PUT
x-ms-date:Thu, 20 Jan 2022 14:55:51 GMT
x-ms-meta-name:value
x-ms-version:2017-04-17
/xxxxx/test/testdir
comp:metadata
restype:directory'.
At line:26 char:8
+ $res = Invoke-WebRequest $URI -Method 'Put' -Headers $headers -UseBas ...
+        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:Htt 
   pWebRequest) [Invoke-WebRequest], WebException
    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShe 
   ll.Commands.InvokeWebRequestCommand

Solution

  • Please change the following line of code:

    $stringToSign = "PUT`n`n`n`n`n`n`n`n`n`n`n`n"+
               "x-ms-date:$date`nx-ms-version:$version`n" + "x-ms-meta-name:value`n" +
               "/$storageAccount/$ShareName/$Directory`ncomp:metadata`nrestype:directory" 
    

    to

    $stringToSign = "PUT`n`n`n`n`n`n`n`n`n`n`n`n"+
               "x-ms-date:$date`n" + "x-ms-meta-name:value`n" + "x-ms-version:$version`n" +
               "/$storageAccount/$ShareName/$Directory`ncomp:metadata`nrestype:directory" 
    

    Essentially the x-ms-* headers must be sorted alphabetically.