Friday, February 12, 2010

Sharing Blobs in Windows Azure

Windows Azure storage makes use of a symmetric key authentication system.  Essentially, we take a 256-bit key and sign each HTTP request to the storage subsystem.  In order to access storage, you have to prove you know the key.  What this means of course is that you need to protect that key well.  It is an all-or-nothing scenario, if you have the key, you can do anything.  If you don't possess the key, you can do nothing*.

The natural question for most folks when they understand this model is, how can I grant access to someone without compromising my master key?  The solution turns out to be something called Shared Access Signatures (SAS) for Windows Azure.  SAS works by specifying a few query string parameters, canonicalizing those parameters, hashing them and signing the hash in the query string.  This creates a unique URL that embeds not only the required access, but the proof that it was created by someone that knew the master key.  The parameters on the query string are:

  • st - this is the start time of when the signature becomes valid.  It is optional.  If not supplied, then now is implied.
  • se - this the the expiration date and time.  All signatures are timebound and this parameter is required.
  • sr - this is the resource that the signature applies to and will be either (b)lob or (c)ontainer.  This is required.
  • sp -this is the permission set that you are granting - (r)ead, (w)rite, (d)elete, and (l)ist.  This is required.
  • si - this is a signed identifier or a named policy that can incorporate any of the previous elements. Optional.
  • sig - this is the signed hash of the querystring and URI that proves it was created with the master key.  It is required.

There is one other caveat that is important to mention here.  Unless you use a signed identifier - what I refer to as a policy - there is no way to create a signature that has a lifetime longer than an hour.  This is for good reason.  A SAS URL that was mistakenly created with an extremely long lifetime and without using the signed idenifier (policy) could not be revoked without changing the master key on the storage account.  If that URL was to leak, your signed resource would be open to abuse for a potentially long time.  By making the longest lifetime of a signature only an hour, we have limited the window in which you are exposed.

If you want to create a longer-lived SAS, you must create a policy.  The policy is very interesting.  Because this policy contains any of those parameters mentioned above and is stored at the service, it means that we can revoke those permission or completely change them instantly.

Let's walk through an example using, where it is trivial to create a SAS.  Once I login to the site, I am going to select the BLOBs option from the navigation tabs on top.  Here I will see a list of all my containers.  I can select a container's Actions menu and click Manage Policies.


Next, I am going to create two policies (signed identifiers), called Read and Write.  These will have different expirations dates and permission sets.  Notice I am not specifying a Start Date, so they are immediately valid.



Next, I am going to select the Actions menu for one of the blobs under this container and click Share.  I am going to apply one of the policies (shared access signature) that I just created by selecting it from the dropdown.


You will notice that the value that I created in the policy fill in the values in the Share BLOB UI and disable you from changing them.  The reason is that a policy is like a template.  If you don't set a value, then you can set (or must set it if it is required).  However, if the policy states one of the parameters, you cannot supply that parameter.  In this case, the 'read' policy that was created specified the expiration (se) and permissions (sp).  It is implied from the dialog selection that the resource (sr) is a (b)lob.  The only value that could be supplied here outside of the policy is the start time (st), which I am not supplying as it is optional.

When I click the Get URL button, I get back a URL that looks like this:


Now, if that URL was to leak and I no longer wanted to provide read access to the blob, I could simply delete the 'read' policy or change the expiration date.  It would instantly be invalidated.  Compare this to the the same signature created without a policy:


This signature could not be revoked until it either expired or I regenerated the master key.

If you want to see how the SAS feature works or easily share blobs or containers in your Windows Azure storage account, give it a try at and see how easy it is to do.


* assuming the key holder has not marked the container as blob- or container-level public access already, in which case it is public read-only.