...
Code Block | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
# inspired by: # https://stackoverflow.com/questions/53653473/generating-an-sas-token-in-java-to-download-a-file-in-an-azure-data-storage-cont?rq=1 # https://purple.telstra.com.au/blog/loading-and-querying-data-in-azure-table-storage-using-powershell # https://docs.microsoft.com/en-us/rest/api/storageservices/authorize-with-shared-key function Create-Signature( [string] $Operation, [string] $Container, [string] $Blob, [string] $Account, [string] $AccessKey, [string] $Version, [DateTime] $Now, [int] $ContentLength=-1 ) { [Reflection.Assembly]::LoadWithPartialName("System.Web") | Out-Null if ( $ContentLength -gt -1 ) { $contentLengthValue = $ContentLength } else { $contentLengthValue = '' } $partToSign = "`n" ` + "`n" ` + "`n" ` + (($ContentLength -gt -1) ? $ContentLength : '') $contentLengthValue + "`n" ` + "`n" ` + "`n" ` + "`n" ` + "`n" ` + "`n" ` + "`n" ` + "`n" ` + "`n" ` + "x-ms-blob-type:BlockBlob" + "`n" ` + "x-ms-date:$(Get-Date (Get-Date $Now).ToUniversalTime() -Format 'R')" + "`n" ` + "x-ms-version:$Version" + "`n" switch ( $Operation ) { 'GET' { $stringToSign = 'GET' ` + $partToSign ` + "/$Account/$Container/$Blob" break } 'PUT' { $stringToSign = 'PUT' ` + $partToSign ` + "/$Account/$Container/$Blob" break } 'LIST' { $stringToSign = "GET" ` + $partToSign ` + "/$Account/$Container" + "`n" ` + "comp:list" + "`n" ` + "restype:container" break } default { throw "invalid operation: $Operation" } } $hmac = New-Object System.Security.Cryptography.HMACSHA256 $hmac.key = [Convert]::FromBase64String( $AccessKey ) $signature = $hmac.ComputeHash( [Text.Encoding]::UTF8.GetBytes( $stringToSign ) ) $signature = [Convert]::ToBase64String( $signature ) Write-Debug "container: $Container" Write-Debug "Accoount: $Account" Write-Debug "AccessKey: $AccessKey" Write-Debug "stringToSign: $stringToSign" $signature } function Invoke-BlobRequest( [Uri] $Uri, [string] $Account, [string] $Signature, [DateTime] $Now, [string] $Version, [string] $Method='GET', [string] $FilePath='' ) { $requestParams = @{} $requestParams.Add( 'Uri', $Uri ) $requestParams.Add( 'Method', $Method ) if ( $FilePath ) { $requestParams.Add( 'Infile', $FilePath ) } $requestParams.Add( 'Headers', @{ ` 'x-ms-blob-type' = 'BlockBlob'; ` 'x-ms-date' = "$(Get-Date (Get-Date $Now).ToUniversalTime() -Format 'R')"; ` 'x-ms-version' = $Version; ` 'Authorization' = "SharedKey $($Account):$($Signature)" ` } ` ) Write-Debug ".... Invoke-WebRequest: $Uri" $requestParams.Keys | % { if ( $_ -eq 'Headers' ) { $item = $_ $requestParams.Item($_).Keys | % { Write-Debug "...... Headers $_ : $($requestParams.Item($item).Item($_))" } } else { Write-Debug "...... $_ $($requestParams.Item($_))" } } # run the web service request $response = Invoke-WebRequest @requestParams $response } # ---------- ---------- ---------- # Main # ---------- ---------- ---------- $ownerAccount = '<storage account>' $ownerAccessKey = '<storage account access key>' $requesterAccount = '<requester account>' $version = '2019-10-10' # consider badly synchronized server time and start 3 minutes in the past $now = (Get-Date).ToUniversalTime().AddMinutes(-3) Write-Host "`n" Write-Host "# ++++++++++++++++++++++++++++++" Write-Host "# List Blobs in Container" Write-Host "# ++++++++++++++++++++++++++++++" # step 1: create signature $container = 'yade' $signature = Create-Signature -Operation 'LIST' -Container $container -Account $ownerAccount -AccessKey $ownerAccessKey -Version $version -Now $now Write-Debug "Signature: $signature" # step 2: send web service request $uri = "https://$($ownerAccount).blob.core.windows.net/$($container)?restype=container&comp=list" $response = Invoke-BlobRequest -Uri $uri -Account $requesterAccount -Signature $signature -Now $now -Version $version -Method 'GET' Write-Host "Status Code: $($response.StatusCode)" Write-Host $response.Content Write-Host "`n" Write-Host "# ++++++++++++++++++++++++++++++" Write-Host "# Get Blob from Container" Write-Host "# ++++++++++++++++++++++++++++++" # step 1: create signature $container = 'yade' $blob = 'test.txt' $signature = Create-Signature -Operation 'GET' -Container $container -Blob $blob -Account $ownerAccount -AccessKey $ownerAccessKey -Version $version -Now $now Write-Debug "Signature: $signature" # step 2: send web service request $uri = "https://$($ownerAccount).blob.core.windows.net/$($container)/$($blob)" $response = Invoke-BlobRequest -Uri $uri -Account $requesterAccount -Signature $signature -Now $now -Version $version -Method 'GET' Write-Host "Status Code: $($response.StatusCode)" Write-Host $response.Content Write-Host "`n" Write-Host "# ++++++++++++++++++++++++++++++" Write-Host "# Write Blob to Container" Write-Host "# ++++++++++++++++++++++++++++++" # step 1: create signature $container = 'yade' $filePath = "c:/tmp/some_blob.txt" $blob = (Get-Item $filePath).Name $signature = Create-Signature -Operation 'PUT' -Container $container -Blob $blob -Account $ownerAccount -AccessKey $ownerAccessKey -Version $version -Now $now -ContentLength (Get-Content $filePath -Raw).length Write-Debug "Signature: $signature" # step 2: send web service request $uri = "https://$($ownerAccount).blob.core.windows.net/$($container)/$($blob)" $response = Invoke-BlobRequest -Uri $uri -Account $requesterAccount -Signature $signature -Now $now -Version $version -Method 'PUT' -FilePath $filePath Write-Host "Status Code: $($response.StatusCode)" Write-Host $response.Content |
Explanations
The Shared Key authentication enable unlimited access i.e it does not have any expiry. Refer to the Azure article Authorize with Shared Key for reference. The above PowerShell script creates the Shared Key for three operation LIST, GET, PUT. The three operation support three different process:
...