Storing the Big Stuff in Blob Storage

Often mobile applications need to store and retrieve large object data, typically photos and video. This is where Azure blog storage comes into play. In order to write into blob storage you need an access key. However, you’d never distribute an actual access key out to a mobile application, even temporarily, as it’s a really bad idea – if someone gets hold of the access key they have access to everything stored in your blob storage. Luckily blob storage has the notion of shared access signatures which you can think of as short term access passes to blob storage. These are typically created using a full access key and as such this operation is done service side.

I’m going to create a dedicated API just for granting shared access signatures to specific containers (which you can think of as single level folders). In this case the containers will be created with public read access on the contents – since the list of blobs per container will be protected and clients will still need a shared access signature in order to write to containers, this should be ample security for a large proportion of application scenarios.

I’ll start off by creating a new Storage area within the Azure management portal.

image

Once created you’ll need to record the storage account name (realestateinspector) and the storage account access key. Add these values into the appSettings section of the web.config file for the Azure Mobile Service

<appSettings>

  <add key=”STORAGE_ACCOUNT_NAME”
       value=”realestateinspector” />
  <add key=”STORAGE_ACCOUNT_ACCESS_KEY”
       value=”LxWu0q2UvQ7ddxXvIP3UfV4ozDkLpgaSkUx————————————33WBYHTpTrAGaHjLoynH+61ng==” />

I’ll create a new controller in my Azure Mobile Service based on the Custom Controller item template

image

The bulk of this api controller sits within a single GET operation:

[AuthorizeLevel(AuthorizationLevel.User)]
public class SharedAccessSignatureController : ApiController
{
    public ApiServices Services { get; set; }

    public async Task<string> Get(string containerToAccess)
    {
        var sas = string.Empty;

        if (!string.IsNullOrEmpty(containerToAccess))
        {
            // Try to get the Azure storage account token from app settings. 
            string storageAccountName;
            string storageAccountKey;

            if (Services.Settings.TryGetValue(“STORAGE_ACCOUNT_NAME”, out storageAccountName) &&
                Services.Settings.TryGetValue(“STORAGE_ACCOUNT_ACCESS_KEY”, out storageAccountKey))
            {
                // Set the URI for the Blob Storage service.
                var blobEndpoint = new Uri(string.Format(“
https://{0}.blob.core.windows.net”, storageAccountName));

                // Create the BLOB service client.
                var blobClient = new CloudBlobClient(blobEndpoint, new StorageCredentials(storageAccountName, storageAccountKey));

                // Create a container, if it doesn’t already exist.
                var container = blobClient.GetContainerReference(containerToAccess);
                await container.CreateIfNotExistsAsync();

                // Create a shared access permission policy.
                var containerPermissions = new BlobContainerPermissions();

                // Enable anonymous read access to BLOBs.
                containerPermissions.PublicAccess = BlobContainerPublicAccessType.Blob;
                container.SetPermissions(containerPermissions);

                // Define a policy that gives write access to the container for 1h
                var sasPolicy = new SharedAccessBlobPolicy()
                {
                    SharedAccessStartTime = DateTime.UtcNow,
                    SharedAccessExpiryTime = DateTime.UtcNow.AddMinutes(59).AddSeconds(59),
                    Permissions = SharedAccessBlobPermissions.Write | SharedAccessBlobPermissions.Read
                };

                sas = container.GetSharedAccessSignature(sasPolicy);
            }
        }

        return sas;
    }
}

If you change the AuthorizationLevel to Anonymous you can run up this controller and use Fiddler to generate the shared access signature by invoking a GET on (eg http://localhost:51539/api/SharedAccessSignature/test, where test is the name of the container we’re requesting access to. If you want to check that the container has been created and the appropriate security set, you can use the CloudBerry Explorer for Azure Blob Storage.

image

After entering credentials you can immediately see the folders in your blob storage which will in this case have the container “test” which was created when I made the request to the SharedAccessSignature service.

image

You can also use Fiddler to prepare and launch a query – don’t forget to switch the AuthorizationLevel back to User before deploying your services otherwise anyone will be able to access content from your blob storage.

Leave a comment