Search icon CANCEL
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
Microsoft Windows Azure Development Cookbook

You're reading from   Microsoft Windows Azure Development Cookbook Realize the full potential of Windows Azure with this superb Cookbook that has over 80 recipes for building advanced, scalable cloud-based services. Simply pick the solutions you need to answer your requirements immediately.

Arrow left icon
Product type Paperback
Published in Aug 2011
Publisher Packt
ISBN-13 9781849682220
Length 392 pages
Edition 1st Edition
Languages
Tools
Arrow right icon
Author (1):
Arrow left icon
Neil Mackenzie Neil Mackenzie
Author Profile Icon Neil Mackenzie
Neil Mackenzie
Arrow right icon
View More author details
Toc

Table of Contents (16) Chapters Close

Microsoft Windows Azure Development Cookbook
Credits
About the Author
About the Reviewers
www.PacktPub.com
Preface
1. Controlling Access in the Windows Azure Platform FREE CHAPTER 2. Handling Blobs in Windows Azure 3. Going NoSQL with Windows Azure Tables 4. Disconnecting with Windows Azure Queues 5. Developing Hosted Services for Windows Azure 6. Digging into Windows Azure Diagnostics 7. Managing Hosted Services with the Service Management API 8. Using SQL Azure 9. Looking at the Windows Azure AppFabric Index

Creating a Shared Access Signature for a container or blob


The Windows Azure Blob Service supports fully authenticated requests, anonymous requests, and requests authenticated by a temporary access key referred to as a Shared Access Signature. The latter allows access to containers or blobs to be limited to only those in possession of the Shared Access Signature.

A Shared Access Signature is constructed from a combination of:

  • Resource (container or blob)

  • Access rights (read, write, delete, list)

  • Start time

  • Expiration time

These are combined into a string from which a 256-bit, hash-based message authentication code (HMAC) is generated. An access key for the storage account is used to seed the HMAC generation. This HMAC is referred to as a shared access signature. The process of generating a Shared Access Signature requires no interaction with the Blob service. A shared access signature is valid for up to one hour, which limits the allowable values for the start time and expiration time.

When using a Shared Access Signature to authenticate a request, it is submitted as one of the query string parameters. The other query parameters comprise the information from which the shared access signature was created. This allows the Blob service to create a Shared Access Signature, using the access key for the storage account, and compare it with the Shared Access Signature submitted with the request. A request is denied if it has an invalid Shared Access Signature.

An example of a storage request for a blob named theBlob in a container named chapter1 is:

GET /chapter1/theBlob

An example of the query string parameters is:

st=2011-03-22T05%3A49%3A09Z
&se=2011-03-22T06%3A39%3A09Z
&sr=b
&sp=r
&sig=GLqbiDwYweXW4y2NczDxmWDzrJCc89oFfgBMTieGPww%3D

The st parameter is the start time for the validity of the Shared Access Signature. The se parameter is the expiration time for the validity of the Shared Access Signature. The sr parameter specifies that the Shared Access Signature is for a blob. The sp parameter specifies that the Shared Access Signature authenticates for read access only. The sig parameter is the Shared Access Signature. A complete description of these parameters is available on MSDN at the following URL:

http://msdn.microsoft.com/en-us/library/ee395415.aspx

Once a Shared Access Signature has been created and transferred to a client, no further verification of the client is required. It is important, therefore, that the Shared Access Signature be created with the minimum period of validity and that its distribution be restricted as much as possible. It is not possible to revoke a Shared Access Signature created in this manner.

In this recipe, we will learn how to create and use a Shared Access Signature.

Getting ready

This recipe assumes the following is in the application configuration file:

<appSettings>
   <add key="DataConnectionString"value="DefaultEndpointsProtocol=https;AccountName={ACCOUNT_NAME};AccountKey={ACCOUNT_KEY}"/>
   <add key="AccountName" value="{ACCOUNT_NAME}"/>
   <add key="AccountKey" value="{ACCOUNT_KEY}"/>
</appSettings>

We must replace {ACCOUNT_NAME} and {ACCOUNT_KEY} with appropriate values for the account name and access key.

How to do it...

We are going to create and use Shared Access Signatures for a blob. We do this as follows:

  1. Add a class named SharedAccessSignaturesExample to the project.

  2. Add the following using statements to the top of the class file:

    using Microsoft.WindowsAzure;
    using Microsoft.WindowsAzure.StorageClient;
    using System.Configuration;
    using System.Net;
    using System.IO;
    using System.Security.Cryptography;
  3. Add the following private members to the class:

    private String blobEndpoint;
    private String accountName;
    private String accountKey;
  4. Add the following constructor to the class:

    SharedAccessSignaturesExample()
    {
       CloudStorageAccount cloudStorageAccount =CloudStorageAccount.Parse(ConfigurationManager.AppSettings["DataConnectionString"]);
       blobEndpoint =cloudStorageAccount.BlobEndpoint.AbsoluteUri;
       accountName = cloudStorageAccount.Credentials.AccountName;
       
    
       StorageCredentialsAccountAndKey accountAndKey =cloudStorageAccount.Credentials asStorageCredentialsAccountAndKey;
       accountKey =accountAndKey.Credentials.ExportBase64EncodedKey();
    }
  5. Add the following method, creating a container and blob, to the class:

       private void CreateContainerAndBlob(String containerName,String blobName)
       {
         CloudStorageAccount cloudStorageAccount =CloudStorageAccount.Parse(ConfigurationManager.AppSettings["DataConnectionString"]);
         CloudBlobClient cloudBlobClient =cloudStorageAccount.CreateCloudBlobClient();
         CloudBlobContainer cloudBlobContainer =new CloudBlobContainer(containerName, cloudBlobClient);
         cloudBlobContainer.Create();
         CloudBlockBlob cloudBlockBlob =cloudBlobContainer.GetBlockBlobReference(blobName);
         cloudBlockBlob.UploadText("This weak and idle theme.");
    }
  6. Add the following method, getting a Shared Access Signature, to the class:

    private String GetSharedAccessSignature(String containerName, String blobName)
    {
       SharedAccessPolicy sharedAccessPolicy =new SharedAccessPolicy()
       {
          Permissions = SharedAccessPermissions.Read,
          SharedAccessStartTime =DateTime.UtcNow.AddMinutes(-10d),
          SharedAccessExpiryTime =DateTime.UtcNow.AddMinutes(40d)
       };
    
       CloudStorageAccount cloudStorageAccount =CloudStorageAccount.Parse(ConfigurationManager.AppSettings["DataConnectionString"]);
       CloudBlobClient cloudBlobClient =cloudStorageAccount.CreateCloudBlobClient();
       CloudBlobContainer cloudBlobContainer =new CloudBlobContainer(containerName, cloudBlobClient);
       CloudBlockBlob cloudBlockBlob =cloudBlobContainer.GetBlockBlobReference(blobName);
    
       String sharedAccessSignature =cloudBlockBlob.GetSharedAccessSignature(sharedAccessPolicy);
    
       return sharedAccessSignature;
    }
  7. Add the following method, creating a Shared Access Signature, to the class:

    private String CreateSharedAccessSignature(String containerName, String blobName, String permissions)
    {
       String iso8061Format = "{0:yyyy-MM-ddTHH:mm:ssZ}";
       DateTime startTime = DateTime.UtcNow;
       DateTime expiryTime = startTime.AddHours(1d);
       String start = String.Format(iso8061Format, startTime);
       String expiry = String.Format(iso8061Format, expiryTime);
       String stringToSign =String.Format("{0}\n{1}\n{2}\n/{3}/{4}\n",permissions, start, expiry, accountName, containerName);
    
       String rawSignature = String.Empty;
       Byte[] keyBytes = Convert.FromBase64String(accountKey);
       using (HMACSHA256 hmacSha256 = new HMACSHA256(keyBytes))
       {
          Byte[] utf8EncodedStringToSign =System.Text.Encoding.UTF8.GetBytes(stringToSign);
          Byte[] signatureBytes =hmacSha256.ComputeHash(utf8EncodedStringToSign);
          rawSignature = Convert.ToBase64String(signatureBytes);
       }
    
       String sharedAccessSignature =String.Format("?st={0}&se={1}&sr=c&sp={2}&sig={3}",Uri.EscapeDataString(start),Uri.EscapeDataString(expiry),permissions,Uri.EscapeDataString(rawSignature));
    
       return sharedAccessSignature;
    }
  8. Add the following method, authenticating with a Shared Access Signature, to the class:

    private void AuthenticateWithSharedAccessSignature(String containerName, String blobName,String sharedAccessSignature)
    {
       StorageCredentialsSharedAccessSignature storageCredentials= new StorageCredentialsSharedAccessSignature(sharedAccessSignature);
       CloudBlobClient cloudBlobClient =new CloudBlobClient(blobEndpoint, storageCredentials);
    
       CloudBlobContainer cloudBlobContainer =new CloudBlobContainer(containerName, cloudBlobClient);
       CloudBlockBlob cloudBlockBlob =cloudBlobContainer.GetBlockBlobReference(blobName);
       String blobText = cloudBlockBlob.DownloadText();
    }
  9. Add the following method, using a Shared Access Signature, to the class:

    private void UseSharedAccessSignature(String containerName, String blobName,String sharedAccessSignature)
    {
       String requestMethod = "GET";
       String urlPath = String.Format("{0}{1}/{2}{3}",
         blobEndpoint, containerName, blobName,sharedAccessSignature);
       Uri uri = new Uri(urlPath);
       HttpWebRequest request =(HttpWebRequest)WebRequest.Create(uri);
       request.Method = requestMethod;
       using (HttpWebResponse response =(HttpWebResponse)request.GetResponse())
       {
          Stream dataStream = response.GetResponseStream();
          using (StreamReader reader =new StreamReader(dataStream))
          {
             String responseFromServer = reader.ReadToEnd();
          }
       }
    }
  10. Add the following method, using the methods added earlier, to the class:

    public static void UseSharedAccessSignaturesExample()
    {
       String containerName = "{CONTAINER_NAME}";
       String blobName = "{BLOB_NAME}";
    
       SharedAccessSignaturesExample example =new SharedAccessSignaturesExample();
    
       example.CreateContainerAndBlob(containerName, blobName);
    
       String sharedAccessSignature1 =example.GetSharedAccessSignature(containerName, blobName);
       example.AuthenticateWithSharedAccessSignature(containerName, blobName, sharedAccessSignature1);
    
       String sharedAccessSignature2 =example.CreateSharedAccessSignature(containerName, blobName, "rw");
       example.UseSharedAccessSignature(containerName, blobName, sharedAccessSignature2);
    }
    

How it works...

In steps 1 and 2, we set up the class. In step 3, we add some private members for the blob endpoint, as well as the account name and access key which we initialize in the constructor we add in step 4. In step 5, we create a container and upload a blob to it.

In step 6, we use the GetSharedAccessSignature() method of the CloudBlockBlob class to get a shared access signature based on a SharedAccessPolicy we pass into it. In this SharedAccessPolicy, we specify that we want read access on a blob from 10 minutes earlier to 40 minutes later than the current time. The fuzzing of the start time is to minimize any risk of the time on the local machine being too far out of sync with the time on the storage service. This approach is the easiest way to get a shared access signature.

In step 7, we construct a Shared Access Signature from first principles. This version does not use the Storage Client library. We generate a string to sign from the account name, desired permissions, start, and expiration time. We initialize an HMACSHA256 instance from the access key, and use this to generate an HMAC from the string to sign. We then create the remainder of the query string while ensuring that the data is correctly URL encoded.

In step 8, we use a shared access signature to initialize a StorageCredentialsSharedAccessSignature instance, which we use to create a CloudBlobClient instance. We use this to construct the CloudBlobContainer and CloudBlobClient instances we use to download the content of a blob.

In step 9, we use HttpWebRequest and HttpWebResponse objects to perform an anonymous download of the content of a blob. We construct the query string for the request using the Shared Access Signature and direct the request to the appropriate blob endpoint. Note that when constructing urlPath for the storage emulator, we must add a / between {0} and {1} because of a difference in the way the Storage Client library constructs the endpoint for the storage emulator and the storage service. For example, we need to use the following for the storage emulator:

String urlPath = String.Format("{0}/{1}/{2}{3}",blobEndpoint, containerName, blobName,sharedAccessSignature);

In step 10, we add a helper method that invokes all the methods we added earlier. We must replace {CONTAINER_NAME} and {BLOB_NAME} with appropriate names for the container and blob.

There's more...

In step 7, we could create a Shared Access Signature based on a container-level access policy by replacing the definition of stringToSign with the following:

String stringToSign = String.Format("\n\n\n/{0}/{1}\n{2}", accountName, containerName, policyId);

policyId specifies the name of a container-level access policy.

See also

  • The recipe named Using a container-level access policy in this chapter

You have been reading a chapter from
Microsoft Windows Azure Development Cookbook
Published in: Aug 2011
Publisher: Packt
ISBN-13: 9781849682220
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at ₹800/month. Cancel anytime