Saltar al contenido
Programemos.net Decisiones pragmáticas sobre .NET, Azure, arquitectura de software e IA.
AZURE

AzureWebJobsStorage con identidad administrada

AzureWebJobsStorage no tiene que guardar una cadena de conexión. Azure Functions puede usar una identidad administrada para acceder al almacenamiento del runtime y eliminar ese secreto de la configuración. Es distinto de la conexión que tu propio código usa para leer o escribir blobs, explicada en la publicación anterior.

Entendiendo el funcionamiento de las Azure Functions

Cuando creamos un proyecto de Azure Function y trabajamos localmente con un almacenamiento(Azurite), se genera un archivo llamado local.settings.json. Este archivo tendrá una estructura similar a la siguiente:

{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "dotnet"
}
}

Me gustaría enfocarme en el parámetro AzureWebJobsStorage, el cual representa la cadena de conexión de una cuenta de almacenamiento que el entorno de ejecución de Azure Functions utiliza para realizar operaciones de coordinación general. Algunas de esta operaciones incluyen la administración de claves, la gestión de desencadenadores, temporizadores y los puntos de comprobación de Event Hubs.

En otras palabras, este parámetro representa la cuenta de almacenamiento que el entorno de Azure Functions utiliza internamente para almacenar información necesaria para su correcto funcionamiento. Por ejemplo, cuando se trabaja con Azure Function Durable, se generan tablas específicas utilizadas para el registro y control de actividades ejecutadas.

Cuando se utiliza UseDevelopmentStorage=true, se hace referencia al emulador Azurite, el cual se emplea para el desarrollo local de Azure Storage. Sin embargo, en producción, esta configuración debería apuntar a una cadena de conexión de una cuenta de almacenamiento real en Azure. Es fundamental comprender que esta cuenta de almacenamiento es utilizada por el entorno de ejecución de Azure Functions sin importar el tipo de desencadenador que se esté utilizando. Por eso al momento de crear el proyecto de Azure Function se solicita que indiquemos una cuenta de almacenamiento.

Modificando nuestra Azure Function

Por defecto, Azure Functions obtiene una cadena de conexión desde AzureWebJobsStorage. En Azure podemos reemplazarla por una configuración basada en identidad. Para una cuenta en la nube pública, sin DNS personalizado, la forma más simple con la identidad asignada por el sistema es:

{
"AzureWebJobsStorage__accountName": "<storage_account_name>"
}

Las URI separadas para Blob, Queue y Table siguen siendo útiles en nubes soberanas o cuando existe un DNS personalizado:

{
"AzureWebJobsStorage__blobServiceUri": "https://<storage_account_name>.blob.core.windows.net",
"AzureWebJobsStorage__queueServiceUri": "https://<storage_account_name>.queue.core.windows.net",
"AzureWebJobsStorage__tableServiceUri": "https://<storage_account_name>.table.core.windows.net"
}

Si usamos una identidad administrada asignada por el usuario, añadimos su identificador de cliente:

{
"AzureWebJobsStorage__clientId":"<Client_ID>",
"AzureWebJobsStorage__credential":"managedidentity"
}

El resultado para una cuenta estándar sería:

{
"AzureWebJobsStorage__accountName": "<storage_account_name>",
"AzureWebJobsStorage__credential": "managedidentity",
"AzureWebJobsStorage__clientId": "<client_id>"
}

Después eliminamos la configuración original AzureWebJobsStorage, porque ya no queremos que el host encuentre una cadena con la clave de la cuenta.

Esta configuración pertenece al entorno de Azure. Microsoft indica que no se debe establecer AzureWebJobsStorage__credential durante el desarrollo local. En local.settings.json conserva AzureWebJobsStorage: UseDevelopmentStorage=true para trabajar con Azurite y no subas ese archivo al repositorio.

Asignación de permisos a la entidad administrada de nuestra Azure Function

La identidad necesita permisos de plano de datos sobre la cuenta. Para el almacenamiento del host, el punto de partida documentado es Storage Blob Data Owner. Eso no significa asignar el rol genérico Owner de Azure ni conceder control total sobre toda la suscripción.

Para el caso de la cuenta de almacenamiento usada por Azure Function también necesitamos conceder permisos necesarios para las operaciones administrativas (Crear leer, escribir etc.). Por ejemplo, las Azure Fuction Durable generan varias tablas para control de sus actividad, por lo cual necesitaría permiso para esta acción de crear y escribir una tabla en la cuenta de almacenamiento.

Cada disparador de función(trigger) utiliza de manera diferente el recuso de almacenamiento, por lo cual debemos asignar permisos que cubran cada una de las necesidades. Eso nos obligaría a estudiar el funcionamiento interno funciones y entender como usan el recurso de almacenamiento. Pero como Microsoft nos quiere facilitar el trabajo, ellos generaron una tabla donde se explica el permiso necesario según el disparador que usemos (En enlace de referencia puedes ver la tabla).

Permisos requeridos para las Azure Function

Los roles adicionales dependen de las extensiones y disparadores. Por ejemplo, un Blob trigger puede requerir también Storage Account Contributor y Storage Queue Data Contributor sobre la cuenta usada por AzureWebJobsStorage. Durable Functions y otros bindings tienen necesidades distintas: consulta la tabla oficial y asigna únicamente lo que usa tu aplicación.

Con la información de la tabla anterior puedes ir al recurso de almacenamiento y conceder los roles requeridos por nuestra aplicación.

Límites y comprobaciones antes de desplegar

Comprueba que las versiones de tus extensiones admiten conexiones basadas en identidad. Si el plan usa Azure Files para contenido, ten presente que esa conexión no admite identidad administrada en todos los escenarios y puede seguir necesitando una cadena. En Linux Consumption, el despliegue también puede requerir un paquete externo cuando AzureWebJobsStorage usa identidad.

La mejora de seguridad es real: eliminamos una clave con acceso amplio y pasamos a una identidad auditable, revocable y limitada por roles. La configuración correcta no consiste en dar más permisos hasta que funcione, sino en entender qué usa el host y aplicar mínimo privilegio.

Referencias

Jose Antonio Arias
Jose Antonio Arias

Senior .NET Developer e Ingeniero en Informática con amplia experiencia en backend, Azure, DevOps, arquitectura e IA empresarial. Ayudo a convertir problemas y procesos de negocio en soluciones tecnológicas con valor real.