Search code examples
azurepowershellapifilesystemsazure-storage

Creating file system in azure data lake gen2 with calling API in powershell script


I am trying to create file system in existing storage account (data lake gen2). I don't know what is the issue in the code that i am trying to execute. I was looking for solution but couldn't find any.

Here is the code:

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

#name of created storage account
$accountName = 'multiprotocoladls2'
#name of file system that i want to create in existing storage account
$fsName= 'multiprotoadls2fs'

$token = 'here is my token'            
$header = @{
    "Content-Length"="0";
    "x-ms-version"="2018-11-09";
    "Authorization"="Bearer $token"
}

$uri = "https://$accountName.dfs.core.windows.net/" + $fsName + "?resource=filesystem" 

Write-Host $uri 

Invoke-RestMethod -Uri $uri -Method 'PUT' -Headers $header

I am getting following error:

    Invoke-RestMethod : {"error":{"code":"AuthenticationFailed","message":"Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly includin
g the signature.\nRequestId:723b78a9-a01f-002e-6973-5801e3000000\nTime:2019-08-21T22:53:41.6191544Z"}}

I have no idea why. I checked parameters in header etc, tried to do everything according to documentation.

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

Can anyone give me a clue how can i overcome this issue?


Solution

  • It's the authentication issue.

    Here is a good article about how to use ADLS Gen2 api with powershell, works well at my side.

    The code which I have test it with myself:

    $StorageAccountName="xxx"
    $FilesystemName="xxx"
    $AccessKey="xxx"
    
    $date = [System.DateTime]::UtcNow.ToString("R") # ex: Sun, 10 Mar 2019 11:50:10 GMT
    
    $n = "`n"
    $method = "PUT"
    
    $stringToSign = "$method$n" #VERB
    $stringToSign += "$n" # Content-Encoding + "\n" +  
    $stringToSign += "$n" # Content-Language + "\n" +  
    $stringToSign += "$n" # Content-Length + "\n" +  
    $stringToSign += "$n" # Content-MD5 + "\n" +  
    $stringToSign += "$n" # Content-Type + "\n" +  
    $stringToSign += "$n" # Date + "\n" +  
    $stringToSign += "$n" # If-Modified-Since + "\n" +  
    $stringToSign += "$n" # If-Match + "\n" +  
    $stringToSign += "$n" # If-None-Match + "\n" +  
    $stringToSign += "$n" # If-Unmodified-Since + "\n" +  
    $stringToSign += "$n" # Range + "\n" + 
    $stringToSign +=    
                        <# SECTION: CanonicalizedHeaders + "\n" #>
                        "x-ms-date:$date" + $n + 
                        "x-ms-version:2018-11-09" + $n # 
                        <# SECTION: CanonicalizedHeaders + "\n" #>
    
    $stringToSign +=    
                        <# SECTION: CanonicalizedResource + "\n" #>
                        "/$StorageAccountName/$FilesystemName" + $n + 
                        "resource:filesystem"# 
                        <# SECTION: CanonicalizedResource + "\n" #>
    
    $sharedKey = [System.Convert]::FromBase64String($AccessKey)
    $hasher = New-Object System.Security.Cryptography.HMACSHA256
    $hasher.Key = $sharedKey
    
    $signedSignature = [System.Convert]::ToBase64String($hasher.ComputeHash([System.Text.Encoding]::UTF8.GetBytes($stringToSign)))
    
    
    $authHeader = "SharedKey ${StorageAccountName}:$signedSignature"
    
    $headers = @{"x-ms-date"=$date} 
    $headers.Add("x-ms-version","2018-11-09")
    $headers.Add("Authorization",$authHeader)
    
    $URI = "https://$StorageAccountName.dfs.core.windows.net/" + $FilesystemName + "?resource=filesystem"
    
    Try {
        Invoke-RestMethod -method $method -Uri $URI -Headers $headers # returns empty response
    }
    catch {
        $ErrorMessage = $_.Exception.Message
        $StatusDescription = $_.Exception.Response.StatusDescription
        $false
    
        Throw $ErrorMessage + " " + $StatusDescription
    }