0

I have a storage account in Azure which hosts a data lake. I want to authorize a specific directory with SAS token and I was able to do configure it by clicking in the portal. First of all, I created a stored access policy lets call it "external1". The policy does not define a permission or an expiry date, it is just used to be able to revoke the SAS token before the token expires.

After that, I navigated to the container "axexternal" to the directory "/external1/central" and generated a SAS token, defining the stored access policy, permissions and expiration date:

SAS token creation

These steps worked as expected. I need to re-create those SAS token automatically. I chose to use an Automation Account (Authorization by its Identity) and use Powershell script to execute the recreation. In detail, I recreate the Storage Access Key first, and then recreate the SAS token. Since the recreation of the Storage Access Key worked like a charm, I focus on the code of the SAS token recreation.

Unfortunatly the documenation for SAS token is technically available but poor. I am not sure which of the commandlets I have to use to get the same result as I had in the Azure Portal. Is it New-AzStorageAccountKey, New-AzStorageContainerSASToken, New-AzStorageBlobSASToken? None of the possible combination of parameters in the documentation seems to fit for my needs.

I need to pass these parameters to the appropriate commandllet:

  • Which storage access key to use for encryption
  • Stored Access Policy to use
  • Expiration Date
  • Permissions

Moreover, I am not able to understand the purpose of the -Context parameter in these commandlets. Is this context used to connect to the storage and execute the script for the creation of the SAS token or is it used to pass parameters to the commandlet? I tried many variations to achieve the goal, but I failed. Is there anybody able to give me some hints please?

Here is some code I tried:

$ctx = New-AzStorageContext `
    -StorageAccountName $storageAccount `
    -StorageAccountKey $key.Value `
    -Protocol "Https"

$uri = New-AzStorageBlobSASToken `
   -Context $ctx `
   -Container $container `
   -Blob "/external1/central" `
   -Policy $policy 
   -StartTime (Get-Date).AddDays(-1) `
   -ExpiryTime (Get-Date).AddDays(370) `
   -FullUri

Update

I recognized that my post was maybe too unspecific. I want to supplement it with a specific question.

Given

  • A data lake container named "axexternal"
  • A directory "/external1/central"
  • A stored access policy "external1" which does not define permissions or expiry date

Wanted

A Powershell script which creates a SAS for the specific directory "/external1/central" in the container "axexternal"

  • SAS signed by account key
  • SAS uses stored access policy "external1"
  • SAS defines permissions
  • SAS defines expiration date

Thanks for your help, I really appreciate!

Andreas
  • 336
  • 1
  • 8
  • `I tried many variations to achieve the goal, but I failed.` - What failed? – Gaurav Mantri Dec 23 '22 at 10:02
  • Powershell is built using c#. So any c# (NET) code can be converted to powershell. You need to make a request. See following : https://learn.microsoft.com/en-us/azure/storage/common/storage-sas-overview?force_isolation=true#account-sas-1 – jdweng Dec 23 '22 at 10:45
  • @GauravMantri: I was not able to create a SAS token which works the same way as it does when created via the Azure Portal. I didn't find the right commandlet as I told in the description. So I didn't mean a failure like a software exception. – Andreas Dec 23 '22 at 12:04
  • @jdweng: I read the website you provided, but couldn't find any related information that would have helped me. – Andreas Dec 23 '22 at 12:06
  • Look at the link "Create an Account with SAS". There is a Net V11 SDK and a Net v12 SDK. They are different and you have to use the correct version. the v12 requires a key while v11 doesn't use the key. Also see following : https://learn.microsoft.com/en-us/azure/storage/blobs/storage-blob-user-delegation-sas-create-powershell?force_isolation=true – jdweng Dec 23 '22 at 12:17

2 Answers2

1

I tried in my environment and got successfully created azure SAS token with policy:

Initially I created access policy in portal like below:

enter image description here

I executed below command, and it created SAS token with URL successfully.

Command:

$accountname="venkat123"
$accountkey="<your storage account key >"
$containername="docker"
$blob="directory1/demo1mbimage.jpg"
$policy="external"

$ctx = New-AzStorageContext -StorageAccountName $accountName -StorageAccountKey $accountKey

 New-AzStorageBlobSASToken `
   -Context $ctx `
   -Container $containername `
   -Blob $blob `
   -Policy $policy `
   -FullUri

Console: enter image description here

I checked the file URL with browser it worked perfectly.

Browser:

enter image description here

Reference: New-AzStorageBlobSASToken (Az.Storage) | Microsoft Learn

Venkatesan
  • 3,748
  • 1
  • 3
  • 15
  • Thank you very much for your detailed answer, sorry for my late response. I tested the exact same code expect for my own values. Unfortunatly I got an exception: New-AzStorageBlobSASToken : Der Wert darf nicht NULL sein. Parametername: accessPolicy Although I ensured I used $policy="testpolicy" and created the access policy with proper name. That's annyoing. – Andreas Jan 10 '23 at 12:51
  • can you share your code what you have tried? – Venkatesan Jan 10 '23 at 12:54
  • Furthermore, my identity I use for the execution of the Powershell script is the same identity I use to create the SAS token via Azure Portal. So it can't be a permission issue. – Andreas Jan 10 '23 at 12:55
  • Check the [access policy](https://i.imgur.com/hBXsxju.png) is in correct state and start time and end time. – Venkatesan Jan 10 '23 at 13:08
  • `$accountName=""` `$accountKey=""` `$containerName="axexternal"` `$blob="external1/central/index.jpg"` `$policy="testpolicy"` `$ctx = New-AzStorageContext -StorageAccountName $accountName -StorageAccountKey $accountKey` `New-AzStorageBlobSASToken ` ` -Context $ctx ` ` -Container $containerName ` ` -Blob $blob ` ` -Policy $policy ` ` -FullUri` – Andreas Jan 10 '23 at 13:08
  • Thanks for your support. I checked it again. Unfortunatly I can't add a screenshot in the comment: testpolicy, 6 selected, starts at 01.01.2023, ends at 10.01.2024 – Andreas Jan 10 '23 at 13:11
  • It's weird, but I finally was able to find out the error. As soon as I delete all stored access policies except the one I want to use in the script. The script will run successfully. As soon as I add another policy, it fails! Can you confirm this bug? – Andreas Jan 12 '23 at 10:29
0

After investigation I am now sure that currently it is not possible to get the exact same outcome using Powershell as you are able by using the Azure Portal.

The correct cmdlet to be used for my question is New-AzDataLakeGen2SasToken. That's the only way to be able to grant permission to a whole directory of a datalake.

Unfortunatly for this cmdlet there is no parameter to accept a stored access policy. For a datalake both APIs, datalake and BLOB is available for datalakes. As a consequence, the BLOB storage cmdlet New-AzStorageBlobSASToken works, but I didn't find a way to make it work on a directory. This seems to be consequent, since for BLOB storage, directories are just a part of a BLOB name.

Even if the permission to a single BLOB would be sufficient, it would not possible to use a Stored Access Policy which does not define permissions.

So I ended up using New-AzStorageBlobSASToken without using a Stored Access Policy. My plan for escaping problems when a SAS token got exploited is to rename the base folder and create new SAS tokens. This will be sufficient for my use case.

I use this kind of code now:

$container = "ext"
$centralPath = "external1/central"

$storageContext = New-AzStorageContext `
    -StorageAccountName $storageAccount `
    -StorageAccountKey $key.Value

New-AzDataLakeGen2SasToken `
    -Context $storageContext `
    -FileSystem $container `
    -Path $centralPath `
    -Permission "rdl" `
    -StartTime (Get-Date).AddDays(-1).Date `
    -ExpiryTime (Get-Date).AddDays(3).Date `
    -Protocol Https `
    -FullUri
Andreas
  • 336
  • 1
  • 8