Acceso seguro a Azure Blob Storage: Implementación de identidades administradas

En este artículo vamos a utilizar identidades administradas para acceder a recursos de Azure de manera segura, sin necesidad de utilizar credenciales. Cuando se trata de acceder a Azure Blob Storage, uno de los enfoques más utilizados es aprovechar las identidades administradas. Este enfoque es especialmente útil cuando los recursos que necesitan acceder corren en Azure, como Azure Functions. Al utilizar una identidad administrada, se evita la necesidad de lidiar con contraseñas o secretos directamente. En este artículo, nos enfocaremos en la implementación de identidades administradas por el sistema, aunque el proceso para utilizar una identidad administrada por el usuario es similar.

En este artículo, implementaremos una solución práctica utilizando una WebAPI de un solo endpoint en Azure Function. El objetivo de esta WebAPI será leer el contenido de un archivo y devolverlo en la respuesta. Veremos cómo utilizar las identidades administradas en Azure Blob Storage para lograr un acceso seguro y sin contraseñas a los archivos en cuestión.

Configurando la Azure Function

Para implementar la funcionalidad de lectura de archivos y devolución de contenido al cliente, crearemos una Azure Function. En nuestro caso, hemos creado una función llamada «AuthFunction20230517223943″.

Azure Function
Azure Function

Es importante tener en cuenta que, por defecto, las Azure Functions no tienen una identidad administrada asignada. Para habilitar una identidad administrada y asociarla directamente con nuestra Azure Function, seguiremos estos pasos:

  1. Acceder a la configuración de identidad: En el menú de opciones de la función, seleccionaremos «Identity» para acceder a la configuración de identidad.
  2. Configurar una identidad administrada por sistema: Como vamos a utilizar una identidad administrada por sistema, cambiaremos el estado a «Activado». Esto creará automáticamente una identidad asociada a nuestra Azure Function.

Al seguir los pasos anteriores deberíamos ver algo similar a lo siguiente:

Identidad Administrada
Identidad Administrada por el Sistema

Preparando la cuenta de Azure Blob Storage

Para comenzar, es importante definir la cuenta de almacenamiento de Azure a la cual nos conectaremos. En nuestro caso, hemos creado una cuenta llamada «misarchivos».

Mis Archivos en Blob Storage
Mis Archivos

Ahora procederemos a crear un contenedor en nuestra cuenta de almacenamiento. Un contenedor, que se asemeja a una carpeta en un sistema de archivos tradicional, será utilizado para almacenar todos los documentos que vamos a leer. En este caso, nombraremos nuestro contenedor como «Documentos».

Documentos
Documentos

Una vez que hemos creado el contenedor «Documentos», procederemos a crear los archivos que vamos a leer desde nuestra aplicación. En este caso, vamos a crear un archivo llamado «prueba.txt». Es importante asegurarnos de que el acceso a este archivo no sea público, sino protegido o privado. Esto nos permitirá validar la autenticación con la identidad administrada sin necesidad de una contraseña. Si el acceso fuera público, se generaría una URL pública que permitiría acceder al archivo sin ninguna autenticación adicional.

prueba.txt
Prueba.txt

Configuración de permisos en Azure Blog Storage usando la identidad administrada

Ahora nos queda un paso crucial: otorgar permisos a la identidad administrada para que pueda acceder a los archivos en la cuenta de almacenamiento. Para lograr esto, asignaremos un rol específico al usuario dentro del almacenamiento. Es esencial seleccionar un rol que permita las acciones necesarias. En nuestro caso, utilizaremos el rol «Storage Blob Data Reader», que otorga permisos de lectura de datos sobre los blobs en el almacenamiento. Al asignar este rol a la identidad administrada, garantizamos que tenga los privilegios adecuados para obtener los archivos que necesitamos.

Roles
Roles

Ahora es el momento de asignar el rol a la identidad administrada asociada a nuestra Azure Function. Esta identidad será la encargada de acceder al archivo en la cuenta de almacenamiento. Al otorgarle el rol adecuado, estamos concediendo los permisos necesarios a nuestra aplicación para que pueda consultar el archivo sin problemas.

Identidad Administrada por el Sistema
Identidad Administrada por el Sistema

Creando la aplicación que consulta el Azure Blog Storage usando identidad administrada

Como mencioné anteriormente, primero crearemos la aplicación que nos permitirá acceder al contenido del archivo. En este caso, utilizaremos una Azure Function con un desencadenador de tipo HTTP. Esta función responderá a las solicitudes HTTP y devolverá el contenido del archivo solicitado. Es importante destacar que esta es una aplicación de ejemplo y que existen mejores prácticas para utilizar Azure Functions en la entrega de contenido de archivos. Sin embargo, con el objetivo de mantener el ejemplo simple y centrarnos en la autenticación, nos enfocaremos en este aspecto en particular en este artículo.

En este ejemplo creamos un proyecto de Azure Function y creamos el endpoint que devolverá el contenido del archivo.

namespace Auth.Function;
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Azure.Storage.Blobs;
using Azure.Identity;
using Azure.Storage.Blobs.Models;
public class ReadFile
{
    private readonly BlobServiceClient blobServiceClient;
    private readonly string accountStorageName = "misarchivos";
    public ReadFile() => this.blobServiceClient = new BlobServiceClient(new Uri($"https: //{accountStorageName}.blob.core.windows.net"), new DefaultAzureCredential());
    [FunctionName("ReadFile")]
    public async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Function, "get", Route = "prueba")] HttpRequest req, ILogger log)
    {
        string blobName = "prueba.txt";
        string containerName = "documentos";
        BlobContainerClient containerClient = blobServiceClient.GetBlobContainerClient(containerName);
        BlobClient blobClient = containerClient.GetBlobClient(blobName);
        BlobDownloadResult downloadResult = await blobClient.DownloadContentAsync();
        return new OkObjectResult(downloadResult.Content.ToString());
    }
}

Funcionalidad del código anterior: Estableciendo conexión segura y autenticada con Azure Blob Storage

En el código anterior, hemos creado una función que responde a las solicitudes «GET» enviadas a la URL «/api/prueba». Esta función se encarga de establecer una conexión con una cuenta de almacenamiento llamada «misarchivos». A continuación, busca un contenedor específico llamado «documentos» y lee el contenido de un archivo denominado «prueba.txt». Finalmente, este contenido se envía como respuesta al cliente que realizó la solicitud.

En esta sección, nos centraremos en la línea de código específico que establece la conexión segura y autenticada con Azure Blob Storage. Evitaremos adentrarnos demasiado en los detalles de las Azure Function o la estructura de la cuenta de almacenamiento. En cambio, nos enfocaremos en comprender lo que ocurre en la siguiente linea:

 this.blobServiceClient = new BlobServiceClient(new Uri($"https ://{accountStorageName}.blob.core.windows.net"), new DefaultAzureCredential());

La línea de código mencionada establece una conexión segura con Azure Blob Storage utilizando una identidad administrada. La instancia de BlobServiceClient se crea pasando la URI de la cuenta de almacenamiento de Azure Blob Storage y una instancia de DefaultAzureCredential. La identidad administrada, en este caso, es utilizada como parte de la autenticación para acceder a los recursos de Azure Blob Storage. La ventaja de utilizar una identidad administrada es que no es necesario gestionar ni exponer credenciales en el código, lo que mejora la seguridad y simplifica el proceso de autenticación.

Supongo que en este punto te estarás preguntando lo mismo que yo cuando vi este código por primera vez ¿Dónde estoy indicando que estoy usando identidad administrada? ¿Qué identidad administrada estoy usando? Bueno, eso es la magia de usar DefaultAzureCredential de la librería Azure.Identity.

Azure.Identity es un proceso que simplifica la autenticación en Azure. Esta clase selecciona automáticamente la identidad o las credenciales adecuadas según el entorno de ejecución. Por ejemplo, si estás en Azure, utilizará las credenciales de la identidad administrada o el certificado de la máquina virtual. Si estás desarrollando localmente, puede utilizar las credenciales almacenadas en el archivo de configuración o las variables de entorno. En resumen, DefaultAzureCredential simplifica la gestión de las credenciales de autenticación al seleccionar automáticamente las más apropiadas según el contexto de ejecución.

Entonces, para responder a las 2 preguntas que planteamos antes, cuando nuestra aplicación esté corriendo en Azure Function, DefaultAzureCredential tomara la identidad administrada que está asociada a este recurso. DefaultAzureCredential permite especificar cuál queremos usar, pero eso es útil cuando usamos identidades administradas por el usuario.

Publicando nuestra aplicación

Vamos a probar nuestra aplicación directamente en Azure, para eso hacemos el despliegue, puedes usar el mecanismo con el que estés familiarizado o sea más fácil para ti, en mi caso yo recomiendo usar Visual Studio, una vez completado el despliegue veremos nuestra Function ejecutándose en Azure.

Azure Function
Azure Function

Finalmente para concluir probamos nuestro web api, para eso podemos ingresar a la function y luego a la opcion de Code + Test, asi comprobaremos que el contenido del archivo es devuelto por el Web Api.

Probando nuestra API
Probando nuestra API

Aunque en este ejemplo nos enfocamos al uso de la identidad administrada para acceder al Azure Account Storage, el proceso para acceder a los otros recursos mes muy similar e incluso igual en muchos casos.

Bonus:

En la siguiente publicación, puedes ver como podemos mejorar aun más la seguridad al configurar la cuenta de almacenamiento usada por Azure Function(Runtime) en su operación administrativas, para el uso de entidades administradas en lugar de cadenas de conexión.

Conclusión

La implementación de identidades administradas en Azure Blob Storage ofrece una solución segura y eficiente para el acceso a archivos en la nube. Mediante la configuración adecuada de permisos y la asignación de roles a la identidad administrada, podemos garantizar que nuestras aplicaciones accedan de forma autorizada a los recursos de almacenamiento sin necesidad de contraseñas explícitas. Esta práctica simplifica la gestión de acceso y mejora la seguridad, brindando tranquilidad a los desarrolladores y administradores de sistemas. Al utilizar identidades administradas, podemos proteger nuestros datos y mantener un entorno de almacenamiento en la nube más seguro y confiable.

Si quieres seguir aprendiendo sobre estos temas te invito a ver mis otras publicaciones.