Acceso temporal a un blob privado de Windows Azure Storage

Cuando trabajamos con los blobs de Windows Azure Storage podemos hacer uso de distintas maneras del contenido que almacenamos en nuestra cuenta: como CDN, como almacenamiento privado de nuestra aplicación, público y, en ocasiones, una mezcla de todas ellas.

Cuando creamos un contenedor en una cuenta, si no establecemos ningún tipo de permiso, por defecto es de tipo privado. Si quisiéramos que el mismo fuera público bastaría modificar dichos permisos en cualquier momento:

        private CloudBlobContainer GetBlobContainer()
        {
            var client = StorageAccount.CreateCloudBlobClient();
            var container = client.GetContainerReference(CloudConfigurationManager.GetSetting("ContainerName"));

            if (container.CreateIfNotExists())
            {
                container.SetPermissions(new BlobContainerPermissions { PublicAccess = BlobContainerPublicAccessType.Blob });
            }

            return container;
        }

También es posible modificarlos desde Visual Studio, accediendo a nuestra cuenta desde la ventana Server Explorer, seleccionando el contenedor y en sus propiedades realizando el cambio:

Properties blob container from VS

Con el código anterior, modificamos los permisos para poder acceder públicamente a cada uno de los blobs dentro del mismo. Lamentablemente esto es demasiado drástico y, en ocasiones, es posible que no necesitemos un acceso permanente a uno o todos los elementos.

Shared Access Signature

Shared Access Signature es una URI que nos da acceso a elementos restringidos, ya sean queues, tables, containers o blobs. La idea es que podamos proporcionar un acceso dentro de unos márgenes de tiempo a un usuario, sin que el resto de nuestros elementos se vean comprometidos. Con SAS podremos dar acceso de lectura, escritura, eliminación, queries, etcétera con una fecha de inicio y de expiración.

En este caso es concreto, he creado un enlace que llama a una acción de mi aplicación en ASP.NET MVC con el objetivo de que me devuelva la URL que me permitirá descargar el archivo indicado:

        private CloudBlobContainer GetContainer(string containerName)
        {
            var blobClient = account.CreateCloudBlobClient();
            var container = blobClient.GetContainerReference(containerName);
            container.CreateIfNotExists();

            return container;
        }

        public string GetSas(string reference)
        {
            var container = GetContainer(stuffContainer);
            var blob = container.GetBlobReferenceFromServer(reference);

            var sas = blob.GetSharedAccessSignature(new SharedAccessBlobPolicy
            {
                Permissions = SharedAccessBlobPermissions.Read,
                SharedAccessExpiryTime = DateTime.UtcNow.AddMinutes(2)

            });

            return string.Format(CultureInfo.InvariantCulture, "{0}{1}", blob.Uri, sas);
        }

La acción recibe como parámetro la URI donde se encuentra alojado el blob en cuestión y, después de recuperar el contenedor stuff, solicitamos una firma con permiso de lectura y con una expiración de 2 minutos (La fecha de inicio es opcional). Para obtener una URI correcta, es necesario concatenar la URI del blob junto con la firma. De este modo obtendremos una dirección similar a la siguiente:

https://[account].blob.core.windows.net/stuff/arrow_tv_show_wallpaper.jpg?sv=2012-02-12&se=2013-12-08T21%3A24%3A37Z&sr=b&sp=r&sig=m4cdMLAFZU5qXyXjLS6kNtmZID4jfNSwUVwIw7OW1hQ%3D

Espero que sea de utilidad.

¡Saludos!