Gestionar el acceso a Azure Storage a través de Azure Active Directory

Actualizado el 1 de Abril de 2019: esta funcionalidad ya está en GA 🙂

Como sabes, hasta ahora la forma de acceder a una cuenta de Azure Storage era a través del nombre de la misma y un token. Esto hacía que no pudiéramos asignar diferentes niveles de acceso a nuestros datos. Hoy ya podemos decir que existe la posibilidad de gestionar los permisos que un grupo de usuarios, o un usuario en concreto, de Azure Active Directory tiene sobre una cuenta de almacenamiento🤘

Para verlo con un ejemplo, lo único que debemos hacer es asignar los permisos relacionados con Azure Storage en la cuenta de almacenamiento que queremas gestionar el acceso a través de Azure Active Directory. A día de hoy hay tres permisos por defecto y sólo están disponibles para los blobs y las colas:

Azure Storage - Access control - Add role assignment - Nuevos permisos para Azure Storage
Azure Storage – Access control – Add role assignment – Nuevos permisos para Azure Storage

Lo siguiente que necesitas es registrar una aplicación en tu Azure Active Directory, en este caso de tipo Nativo, y asignarle el permiso de Azure Storage, en el apartado API Permissions.

Una vez que tienes asignados los permisos a personas o grupos a tu Azure Storage y tienes tu aplicación registrada en Azure Active Directory, puedes utilizar este código de ejemplo para comprobar el funcionamiento:

using Microsoft.IdentityModel.Clients.ActiveDirectory;
using System;
using System.Globalization;
using Microsoft.WindowsAzure.Storage.Auth;
using Microsoft.WindowsAzure.Storage.Blob;
using System.Threading.Tasks;
using System.Configuration;

namespace StorageAuthenticateWithAzureAD
{
    class Program
    {
        static void Main(string[] args)
        {
            CreateABlob().GetAwaiter();

            Console.ReadLine();

        }

        private async static Task CreateABlob()
        {
            //Get the access token
            var accessToken = GetUserOAuthToken();
            Console.WriteLine(accessToken);

            //Use the access token to create the storage credentials
            var tokenCredential = new TokenCredential(accessToken);
            var storageCredentials = new StorageCredentials(tokenCredential);

            Console.WriteLine("Trying to create a blob...");

            try
            {
                //Create a block blob using those credentials
                var blob = new CloudBlockBlob(new Uri("https://YOUR_STORAGE_ACCOUNT.blob.core.windows.net/sample-container/Blob.txt"), storageCredentials);
                await blob.UploadTextAsync("Blob created by Azure AD authenticated user.");
                Console.WriteLine("Created!");
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error: {0}", ex.Message);
                throw ex;
            }
        }

        static string Setting(string settingName)
        {
            return ConfigurationManager.AppSettings[settingName];
        }

        static string GetUserOAuthToken()
        {
            //Construct the authority string from the Azure AD OAuth endpoint and the tenant ID
            var authority = string.Format(CultureInfo.InvariantCulture, Setting("AuthInstance"), Setting("TenantId"));
            var authContext = new AuthenticationContext(authority);

            //Acquire an access token from Azure AD.
            var result = authContext.AcquireTokenAsync(Setting("ResourceId"),
                                                        Setting("ClientId"),
                                                        new Uri(Setting("RedirectUri")),
                                                        new PlatformParameters(PromptBehavior.Auto)).Result;

            return result.AccessToken;
        }
    }
}

En el archivo App.Config deberás indicar los siguientes valores:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
  </startup>
  <appSettings>
    <add key="AuthInstance" value="https://login.microsoftonline.com/{0}/"/>
    <add key="TenantId" value="YOUR_TENANT_ID"/>
    <add key="ResourceId" value="https://storage.azure.com/"/>
    <add key="ClientId" value="YOUR_CLIENT_ID"/>
    <add key="RedirectUri" value="YOUR_REDIRECT_URI"/>
  </appSettings>
</configuration>

Cuando lo ejecutes, verás que lo primero que ocurre es que se te piden tus credenciales de Azure Active Directory, con el objetivo de recuperar el token. Una vez obtenido se crea un objeto TokenCredential que pasaremos a StorageCredentials y con él intentaremos crear un archivo txt en un contenedor de nuestra cuenta de almacenamiento. Si intentas crear un blob con un usuario que sólo tiene permisos de lectura, la API nos devolverá un 403.

Cuando no tenemos el rol de Data Owner o Data Contributor obtendremos un 403.

Sin embargo, si este tiene el rol de Owner o Contributor podrá crearlo sin problemas.

Imagen de portada por michaelgoodin.

¡Saludos!