Azure shared access signatures and valet key pattern

Valet key pattern is used in cloud hosted applications to delegate access rights (e.g. Read,Write,Delete etc) on a particular resource to an external party using an token (but not sharing the actual credentials) so that they can perform certain operations on that resource directly without involving the main application / service. The external party could be a client like browser or native windows application or a storage system like azure blobs, queues etc.

This helps in offloading some of the compute intensive work from the main application to the client application.In turn this can result in better scalability and performance.

An example scenario

One of the most common scenario which you might find everywhere being shown as an example of this pattern is upload and download of files.

Lets say we have an API app which is being used by a windows client for uploading and downloading files.Users would POST files to this API and then API would upload it to say azure blob storage.Similarly for downloading, the client would make a GET request to the API and API would fetch the file from blob storage and send it to the client.

In this scenario, if you notice, our API app is just acting as an intermediary between blob storage and the client.So the question comes why can’t client directly interact with blob storage and upload and download files.And answer is because to do that client would need to have access to storage credentials and that would not be a good scheme of things if you are sharing your storage credentials with all your clients.Right ?? So we need a mechanism where we can delegate access to clients to a resource in a restricted manner i.e. with restricted permission ,restricted time and without sharing the actual credentials.

Shared access signature

Azure provides mechanism of shared access signatures which can be shared with clients and which provides direct access to a particular resource (Blob ,queues, tables etc.) in your azure storage account in a restricted manner.

Let’s consider another scenario involving queues.Take example of some kind of data processing system where we have two kind of clients

  1. Clients submitting data to be processed
  2. Clients processing the submitted data

And in between we have our service hosted on cloud which integrates these providers and processors.

Now one option to implement this is to do it in traditional way where both kind of clients interact with integration service and the service would put data on the queue and then fetch the data from queue and give it to the clients for processing when asked for.It is not hard to see that soon this service would become a bottleneck as the number of clients on  both the sides increase.

image

Using valet key pattern we can make this model much more scalable where integration service would own the queue but won’t do queue processing rather it would provide access tokens to clients who request and then client can perform required operations .In this case data providers would have restricted access to only add messages to the queue whereas data processors would have only access to read and process messages

image

 

Implementation

Below is a sample using Azure storage client library to showing how to use SAS.

 

Integration Service

public class AccessController : ApiController
 {
 string connectionstring = "DefaultEndpointsProtocol=https;AccountName=sbusdemo;AccountKey=OzUkG74E3bpsWkzwOlGqgDgBU1/7gOPpCtbCIs241tmf2eP07kWlspsU9FdnmDLYKwALiVaIDDOk8QbAfaxP/w==;EndpointSuffix=core.windows.net";
 string queuename = "requestqueue";

 [Route("WriteSas")]
 public string GetWriteSas()
 {
 CloudStorageAccount storageAccount = CloudStorageAccount.Parse(
 connectionstring);

 CloudQueueClient queueClient = storageAccount.CreateCloudQueueClient();

 CloudQueue queue = queueClient.GetQueueReference(queuename);
 queue.CreateIfNotExists();

 //PROVIDE ONLY ADD PERMISSIONS
 SharedAccessQueuePolicy policy = new SharedAccessQueuePolicy()
 {
 SharedAccessExpiryTime = DateTime.UtcNow.Add(TimeSpan.FromHours(1)),
 Permissions = SharedAccessQueuePermissions.Add,

 };
 var sasToken = queue.GetSharedAccessSignature(policy, null);

 //SEND THE SAS URI BACK
 var sasUri = string.Format($"{queue.Uri}{sasToken}");
 return sasUri;

 }

 [Route("ReadSas")]
 public string GetReadSas()
 {
 CloudStorageAccount storageAccount = CloudStorageAccount.Parse(
 connectionstring);

 CloudQueueClient queueClient = storageAccount.CreateCloudQueueClient();

 CloudQueue queue = queueClient.GetQueueReference(queuename);
 queue.CreateIfNotExists();
 SharedAccessQueuePolicy policy = new SharedAccessQueuePolicy()
 {
 SharedAccessExpiryTime = DateTime.UtcNow.Add(TimeSpan.FromHours(1)),
 Permissions = SharedAccessQueuePermissions.ProcessMessages,

 };
 var sasToken = queue.GetSharedAccessSignature(policy, null);
 var sasUri = string.Format($"{queue.Uri}{sasToken}");
 return sasUri;

 }

 }

Data provider

//CALL THE INTEGRATION SERVICE API TO GET SAS URI
 var sasUri = GetSasUri();
 var queue = new CloudQueue(new Uri(sasUri));
 queue.AddMessage(new CloudQueueMessage($"Request for processing - {DateTime.UtcNow.ToLongDateString()}"));

 

Data processor

 var sasUri = GetSasUri();
 var queue = new CloudQueue(new Uri(sasUri));
 var queueOptions = new QueueRequestOptions();

 var message = queue.GetMessage();
 Console.WriteLine(message.AsString);

 

If you notice the only information provided to the clients is a specifically formatted Uri called shared access signature URI which has the SAS token and some other information regarding how long the access is provided for (start time ,expiry time etc).

SAS Uri looks something like this : https://dataprocessing.queue.core.windows.net/requestqueue?sv=2017-04-17&sig=1l2aCfzN1BBpSVLz8xxxxxFyZBBxW7RcxLF5AD4baMae4X8%3D&se=2017-10-14T13%3A18%3A29Z&sp=a. For more details on shared access signatures and what all parts of the SAS Uri means refer this article.

Also here is an excellent course on pluralsight for azure design and implementation cloud design patterns covering valet key and many other patterns.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>