Stored Access Policies in Azure – Overview

Hello again folks. I’ve not posted in a while as I’ve just changed jobs and been spending the majority of time learning the ropes, as is customary 🙂

As my new role is primarily focused on Azure and Azure Stack, I’ve been putting together some ARM templates and walking through the Azure Portal as much as I can.

One of the features I’ve had fun getting to grips with is this idea of Stored access policies, so much so I thought I’d blog about it…so here goes.

 

Overview

Before we get into the details, what are Stored Access Policies and Shared Access Signatures (SAS) in Azure, and why do we care? It’s also worth mentioning that although this concept isn’t new or restricted to Azure, the Azure implementation is what we’re interested in here. Below are a few links to what’s being covered in this guide, the last link is a note of all PowerShell commands used in this guide with a brief explanation if that works better for you:

Prerequisites

Part of this guide is going demo the streaming of a video file from a storage account in a browser (I’ve tested with both Edge and Chrome). You can view a test video file HERE, but we’ll download it from the web and upload it to our storage account later in the guide.

Shared Access Signature

A Shared Access Signature (SAS) is a URI that enables restricted access to entities within a storage account. This URI can then be passed to a client that requires access to a container or a single blob etc. within a storage account without having to give them a storage account key. Giving them a storage account key is basically giving them the keys to the kingdom as far as that storage account is concerned. When creating a SAS, the following properties can be set to control what can be accessed by it:

ResourceDetails
Which services can be accessed, these are:Blob
File
Queue
Table
Which resource types can be accessed, these are:Service
Container
Object
Which permissions are given, chosen from:Read
Write
Delete
List
Add
Create
Update
Process
Start Time and Expiry time of the SASSet a date and time for both. Also select a time zone
Allowed IPsThis can be a single IP or a hyphenated range of IPs
Allowed protocolsChoose between HTTPS or HTTPS and HTTP
Signing keyChoose which key to sign the SAS with, this will be chosen from one of the storage account keys

Here’s what this all looks like in the Azure portal:

clip_image001

Now SAS tokens are great, but they do have their limitations. What happens when you’ve generated a SAS token and passed it across to your client, the token then expires but you decide you want to extend their access for another couple of days. Well in this instance you’d have to generate another token for your client. Is there a way round this? Well that’s where Stored Access Policies come in 🙂

Stored Access Policies

So what are Stored Access Policies? Think of them as a way of grouping your service level SAS tokens by what services and resources they have access to. As these policies are on the server side, they can be modified without having to reissues SAS tokens that were generated from them.  They can also be revoked if required. Here’s an example:

You’ve created a Stored Access Policy that does the following:

  • Allows read access all blobs within a storage account container
  • Allows access for 14 days from its creation
  • Allows access from a single IP address, in this case the clients office IP

The client has advised you that they forgot to mention that they work out of two different offices depending on the day of the week. Now…because we generated the clients SAS token off the back of a Stored Access Policy, we can modify that policy to include the additional IP address specified by the client. The client will then be able to continue using that same SAS token, from their second office…cool right?

Creating a Stored Access Policy Using PowerShell

So now that we’ve went over things in a little detail, let’s get on and create something shall we?

I’m demonstrating doing this in PowerShell as doing it from the Azure portal doesn’t really require too much guidance and any that is you’ll find HERE 🙂

For this example I’ll be creating everything from scratch just to keep things straightforward and allow for easier deletion when we’re finished.

Let’s start by launching an editor like Visual Studio code or PowerShell ISE (elevated of course), I use VSC personally but use whatever works for you.

Before continuing (assuming you’ve not already done it), you’ll need to install Azure for PowerShell, you can find the instructions for that HERE

Now we’ll want to go ahead and log into our Azure account:

Login-AzureRMAccount

You’ll be prompted to enter your Azure AD credentials:

clip_image002
clip_image003

Once logged in, we’ll want to set our Azure context, i.e. select which subscription we’ll be working in.

The command below assumes you only have a single subscription, modify as required:

Set-AzureRMContext -SubscriptionId (Get-AzureRMSubscription).SubscriptionId
clip_image004

As I mentioned above, I’ll be creating everything we need from scratch here, so with that in mind let’s create a new resource group and storage account to work with.

$ResourceGroup = New-AzureRmResourceGroup -Name "Name for your Resource Group" -Location "Your chosen region"
clip_image005

Now that we’ve got a resource group, let’s give it a storage account.

$StorageAccount = New-AzureRmStorageAccount `
    -ResourceGroupName $ResourceGroup.ResourceGroupName `
    -Name "A name for your storage account" `
    -SkuName Standard_LRS `
    -Location $ResourceGroup.location

NOTE: Make sure that the name you give your storage account has no spaces or special characters and is all lowercase or it’ll be rejected.

clip_image006

Before we can continue, we’ll need to create a storage context to work in. To do this, we’ll need to grab the access keys for the storage account we just created.

$AccountKeys = Get-AzureRmStorageAccountKey -ResourceGroupName $ResourceGroup.ResourceGroupName -Name $StorageAccount.StorageAccountName
clip_image007

NOTE:  Yes I know I’ve shown you what the keys to my storage account are, but as I mentioned earlier, this account is for the purposes of this guide and will be deleted before it’s posted. Good eye though 🙂

Now let’s create our storage context

$StorageContext = New-AzureStorageContext -StorageAccountName $StorageAccount.StorageAccountName -StorageAccountKey $AccountKeys[0].Value
clip_image008

Now we’ll need to create a container in our storage account as we need somewhere to upload a test file and it’s the level we’ll be creating our Stored Access Policy against.

$StorageContainer = New-AzureStorageContainer -Name "Name for your container" -Context $StorageContext
clip_image009

Now let’s download a test video file from the web and upload it to our storage account container.

Invoke-WebRequest -Uri "http://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_30mb.mp4" -OutFile C:\Temp\big_buck_bunny_720p_30mb.mp4
Set-AzureStorageBlobContent -File C:\Temp\big_buck_bunny_720p_30mb.mp4 -Container $StorageContainer.Name -Blob "Bunny720p.mp4" -Context $StorageContext -Properties @{"ContentType" = "video/mp4"}
clip_image010

Successful upload looks like:

clip_image011

Now that we’ve uploaded a file to our storage account container, let’s create that Stored Access Policy we’ve been talking about.

The following code will create a policy that gives us read access to blobs in our container for 5 hours from the policies creation time.

$SASPolicy = New-AzureStorageContainerStoredAccessPolicy -Container $StorageContainer.Name -Policy "DFTestSASPolicy" -Context $StorageContext -Permission "r" -StartTime (Get-Date).DateTime -ExpiryTime (Get-Date).AddHours(5).DateTime
Get-AzureStorageContainerStoredAccessPolicy -Container $StorageContainer.Name -Policy $SASPolicy -Context $StorageContext | FL

NOTE: For some reason I’ve yet to look into, the creation of the Storage Access Policy is not stored in the variable as an object, if just holds the name, hence the Get cmdlet afterwards to show you the details of the policy.

clip_image012

Testing and Validation Time

Now we’re in a position to create a Shared Access Signature (SAS) token (using our policy) that’ll give a user restricted access to the blobs in our storage account container.

The code below will create a SAS token, get the URI of the blob we uploaded to the account earlier, append it with the SAS token we created and copy the whole thing into the clipboard ready to be pasted in your browser of choice.

$SASToken = New-AzureStorageContainerSASToken -Name $StorageContainer.Name -Policy $SASPolicy.Policy -Context $StorageContext
(Get-AzureStorageBlob -Blob "Bunny720p.mp4" -Container $StorageContainer.Name -Context $StorageContext).ICloudBlob.Uri.AbsoluteUri + $SASToken | Clip

Pasting the contents of your clipboard into the address bar of a browser (tested with Edge and Chrome) should start streaming the video from your storage account.

The URL should look something like this:

https://dfsasdemostorageaccount.blob.core.windows.net/dfsasdemo/Bunny720p.mp4?sv=2017-04-17&sr=c&si=DFTestSASPolicy&sig=L6C3wapZbDBjAR5kjMbN7dQ7cGl%2BxADi0Z%2FGp0%2Fr84s%3D

I warn you now though, that video starts off all nice, but it gets pretty dark, pretty quick 🙂

clip_image013

NOTE:  Keep that URL in your clipboard for the time being, we’ll be needing it for the next few steps.

Now I said earlier that one of the benefits of using Stored Access Policies is that you can change the policy without invalidating the SAS token you provided to the end user…let’s prove that shall we.

The following PowerShell sets the Expiry date of our Stored Access Policy to be 30 minutes in the past

Set-AzureStorageContainerStoredAccessPolicy -Container $StorageContainer.Name -Policy $SASPolicy -Context $storageContext -ExpiryTime ((Get-Date).AddMinutes(-30))
clip_image014

Now if you paste the URL in your clipboard into the browser, or just refresh the page, you should see the following error.

clip_image015

Let’s set it back again just to complete the loop.

Set-AzureStorageContainerStoredAccessPolicy -Container $StorageContainer.Name -Policy $SASPolicy -Context $storageContext -ExpiryTime ((Get-Date).AddMinutes(30))
clip_image016

NOTE:  If you’ve misplaced the SAS token URL, you can retrieve it again with the following:

(Get-AzureStorageBlob -Blob "Bunny720p.mp4" -Container $StorageContainer.Name -Context $StorageContext).ICloudBlob.Uri.AbsoluteUri + $SASToken | Clip

Pasting it into the browser again, or refreshing the page, should start streaming the video…success!

clip_image017

…and that’s it for this guide folks. I hope this overview helps you get a better understanding of SAS tokens and policies in Azure. As promised at the start of this guide, I’ve listed all the commands I used together so you can grab them if that’s all you need 🙂

See you in the next guide.

PowerShell Commands Used in This Guide

# Log into Azure Account, you will be prompted for your credentials in a pop-up window
Login-AzureRmAccount

# Create a resource group, enter values for -ResourceGroupName and -Location
$ResourceGroup = New-AzureRmResourceGroup -Name "RG Name" -Location "Location"

# Create a storage account, enter value for -Name
$StorageAccount = New-AzureRmStorageAccount `
    -ResourceGroupName $ResourceGroup.ResourceGroupName `
    -Name "Storage Account Name" `
    -SkuName Standard_LRS `
    -Location $ResourceGroup.location

# Get the access keys of the Storage Account you just created
$AccountKeys = Get-AzureRmStorageAccountKey -ResourceGroupName $ResourceGroup.ResourceGroupName -Name $StorageAccount.StorageAccountName

# Create a storage context to work with the storage account you just created. It'll use the first access key on the account
$StorageContext = New-AzureStorageContext -StorageAccountName $StorageAccount.StorageAccountName -StorageAccountKey $AccountKeys[0].Value

# Create a container in the Storage Account you created earlier, enter value for -Name
$StorageContainer = New-AzureStorageContainer -Name "Container Name" -Context $StorageContext

# Download a sample mp4 video file and upload it to the Storage Account container you created earlier
Invoke-WebRequest -Uri "http://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_30mb.mp4" -OutFile C:\Temp\big_buck_bunny_720p_30mb.mp4

Set-AzureStorageBlobContent -File C:\Temp\big_buck_bunny_720p_30mb.mp4 `
                            -Container $StorageContainer.Name `
                            -Blob "Bunny720p.mp4" `
                            -Context $StorageContext `
                            -Properties @{"ContentType" = "video/mp4"}

# Create a Stored Access Policy for the container you created earlier with read access to its blobs and an exiry time of 5 hours from the point of creation
$SASPolicy = New-AzureStorageContainerStoredAccessPolicy -Container $StorageContainer.Name `
                                                         -Policy "DFTestSASPolicy" `
                                                         -Context $StorageContext `
                                                         -Permission "r" `
                                                         -StartTime (Get-Date).DateTime `
                                                         -ExpiryTime (Get-Date).AddHours(5).DateTime

# Create a SAS token using the policy you created earlier
$SASToken = New-AzureStorageContainerSASToken -Name $StorageContainer.Name `
                                              -Policy $SASPolicy `
                                              -Context $StorageContext

# Get the full URL including SAS token to access the video file you uploaded to the storage account earlier
(Get-AzureStorageBlob -Blob "Bunny720p.mp4" -Container $StorageContainer.Name -Context $StorageContext).ICloudBlob.Uri.AbsoluteUri + $SASToken | Clip

<# # Set the Stored Access Policy Expiry time to 30 minutes in the past Set-AzureStorageContainerStoredAccessPolicy -Container $StorageContainer.Name -Policy $SASPolicy -Context $storageContext -ExpiryTime ((Get-Date).AddMinutes(-30)) # Set the Stored Access Policy Expiry time to 30 minutes in the future Set-AzureStorageContainerStoredAccessPolicy -Container $StorageContainer.Name -Policy $SASPolicy -Context $storageContext -ExpiryTime ((Get-Date).AddMinutes(30)) #>

3 Replies to “Stored Access Policies in Azure – Overview”

    1. I was confused because in the Azure Portal you can create a Stored Access Policy, but you can’t use it to create a new SAS. So, your article filled the missing piece with the PowerShell walktrough. Thanks 🙂

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.