Windows Azure Guidance – Using Shared Key Signatures for images in a-Expense

As described before, a-Expense static content (mainly the scanned images uploaded by users) is stored in blobs. As with many other things in life there are quite a few options when it comes to how those images are made available to users.

A key design consideration, is that in Windows Azure all storage subsystems (tables, blobs and queues) are directly addressable from anywhere, not just from your web tier.

For example, a blob in Azure is normally reachable through a URL like:

 

https:// <application>. blob.core.windows.net/ <container>/<blob>

 

So, the classic tiered app that we come to love and blindly draw:

 

image

looks more like this one, provided you have the right credentials.

 

image

This contrasts quite a bit with typical on-premises arrangements, where there are often network barriers to the storage subsystems (e.g. firewalls, subnets, private lans, etc).

Note: SQL Azure is also directly reachable from the internet, but it incorporates a firewall that you have control on. That is, you can define which source IP addresses are allowed for incoming connections into a SQL Azure database.  

Given this, one might wonder what the best way of referencing blob content from a web page is, and as usual, there are tradeoffs and “it depends” :-).

Option 1: just make the blob public

This is the simplest, you just make your blob content public. No access keys are required, and anyone can download the content directly if they know the URL. This is fine if this content is not confidential and you don’t care that it might be leaked. This can be suitable for logos, branding stuff, PDF forms, and the like.

The advantages:

  1. Very simple.
  2. Easily cacheable.
  3. Traffic is offloaded from the web server.
  4. Content can leverage the CDN infrastructure in Azure.

image 

Implementing this is straight forward. The web server would simply generate links to the blob content with the appropriate URL. In a-Expense, the reference to the image is actually stored in the table. Obviously this doesn’t work if your content is confidential (like in a-Expense). Using obfuscation, like through really complex and difficult to remember URL, is a weak protection and not recommended.

 

Option 2: route traffic through the web site 

This is pretty obvious. It is essentially using a “trusted subsystem” model. The web server holds blob access keys that are used on-behalf of the user. This is the approach used to write the image contents to the blob to begin with. The disadvantages are pretty much the opposite of Option #1: all traffic goes through the web site, the app gets slightly more complex, no CDN. One way of implementing this is through a HTTP handler in the web application that intercepts the specific resources and serves them back:

 

image

Option 3: using Shared Access Signatures

Shared Access Signatures is a very cool feature in Windows Azure Storage that allows you to generate time bound, fine-grained access control, blob URLs without opening a whole container to everyone.

A great overview of the feature together with a simple online sample is available here (Steve Marx’s blog), and Ryan & Steve’s CloudCover 8 here.

This is an interesting tradeoff between option #1 and option #2. The browser can pull the content directly from the blob container, but only through a limited time (like the session time) and only for reading. No processing is needed in the web site, except generating the SAS URL, which is a fairly simple process anyway. When the URL expires, the URL becomes invalid and it needs to be re-generated.

This little sample app demonstrates how this works: https://wazdrop.cloudapp.net/ 

SAS URLs look like the one below. You can see how different elements of access control are encoded there (operation, expiry, scope, etc):

image 

This is the approach we will use for a-Expense so we can illustrate how it works, but more importantly because we believe it is a good application of the feature for the system.

Update: link to Steve Marx’s has been updated.