Email copiado — support@tuurt.com
Cargando experiencia
azure · 24 de agosto de 2026 · 7 min

Managed Identity en Azure: cómo sacar las connection strings del código sin depender de un Key Vault mal configurado

Managed Identity resuelve la autenticacion entre recursos de Azure sin guardar credenciales, pero solo si se entiende la diferencia entre identidad de sistema y de usuario, y los errores de RBAC que la rodean.

Por Equipo Tuurt

Managed Identity en Azure: cómo sacar las connection strings del código sin depender de un Key Vault mal configurado

Cada vez que revisamos un proyecto nuevo en Azure, el patrón que más se repite es el mismo: una connection string de SQL Server o una clave de Storage Account guardada en appsettings.json, en una variable de entorno del App Service o, en el peor de los casos, hardcodeada en el código y subida al repositorio en algún commit antiguo que nadie revisó a fondo. La respuesta habitual es "vamos a meter todo en Key Vault", lo cual es correcto, pero deja sin resolver la pregunta que importa: ¿con qué credencial se autentica la aplicación contra ese Key Vault? Si la respuesta sigue siendo "con una connection string o un client secret en una variable de entorno", no se eliminó el problema, se movió un nivel hacia arriba. Managed Identity cierra ese ciclo: una identidad de Azure AD asociada directamente al recurso que ejecuta el código, sin ninguna credencial que alguien tenga que guardar, rotar o filtrar por accidente.

Qué resuelve Managed Identity y qué no

Managed Identity le da a un recurso de Azure —un App Service, una Function App, una VM, un cluster de AKS— una identidad en Azure AD que otros servicios de Azure pueden reconocer y autorizar mediante RBAC. La aplicación pide un token contra esa identidad usando el endpoint de metadata local del recurso, sin que ese token dependa de ningún secreto en configuración. Esto resuelve la autenticación entre recursos de Azure: App Service contra SQL Database, Function App contra Storage, AKS contra Key Vault o Service Bus.

Lo que no resuelve es la autenticación contra servicios que no son de Azure. Una API externa, una base de datos on-premise sin integración con Azure AD o un servicio SaaS de terceros siguen necesitando algún tipo de credencial almacenada, y ahí Key Vault sigue siendo la pieza correcta, solo que ahora la aplicación se autentica contra Key Vault con Managed Identity en lugar de con un secreto propio. La cadena de confianza termina en una identidad administrada por Azure, no en un secreto que alguien escribió en algún lado.

Identidad asignada por el sistema vs. asignada por el usuario

Azure ofrece dos variantes y la diferencia entre ellas no es solo de sintaxis, es de ciclo de vida.

Una identidad asignada por el sistema (system-assigned) se crea junto con el recurso y muere con él. Un App Service con esta identidad habilitada tiene un principalId en Azure AD que existe mientras el App Service exista; si se elimina el recurso, la identidad desaparece automáticamente, y con ella cualquier permiso RBAC que se le hubiera asignado. Es la opción correcta cuando la identidad tiene sentido solo en el contexto de ese recurso específico y no necesita compartirse con nada más.

az webapp identity assign \
  --name pedidos-api \
  --resource-group prod-rg

Una identidad asignada por el usuario (user-assigned) es un recurso independiente en Azure, con su propio ciclo de vida, que se puede asociar a uno o varios recursos a la vez. Tiene sentido cuando varios servicios necesitan compartir el mismo conjunto de permisos —por ejemplo, tres Function Apps que todas necesitan leer del mismo Key Vault— porque en lugar de asignar el rol RBAC tres veces, una por cada identidad de sistema, se asigna una sola vez a la identidad compartida y se asocia esa identidad a los tres recursos.

az identity create \
  --name id-pedidos-shared \
  --resource-group prod-rg

az webapp identity assign \
  --name pedidos-api \
  --resource-group prod-rg \
  --identities /subscriptions/.../resourceGroups/prod-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/id-pedidos-shared

La contrapartida es que una identidad de usuario sobrevive a la eliminación del recurso que la usa: si se borra el App Service y nadie borra también la identidad, queda un principal con permisos RBAC activos sin ningún recurso real detrás, exactamente el tipo de recurso huérfano que un advisor de seguridad marca meses después sin que nadie recuerde de dónde salió.

Usarla desde el código: DefaultAzureCredential

En .NET, la pieza que hace que el mismo código funcione en local y en Azure sin cambiar una línea es DefaultAzureCredential, de Azure.Identity. Internamente prueba una cadena de mecanismos de autenticación en orden —variables de entorno, Managed Identity, Visual Studio, Azure CLI, entre otros— y usa el primero que encuentra disponible.

var credential = new DefaultAzureCredential();

var client = new SecretClient(
    new Uri("https://kv-pedidos-prod.vault.azure.net/"),
    credential);

var secret = await client.GetSecretAsync("connection-string-sql");

En producción, dentro del App Service, DefaultAzureCredential detecta el endpoint de metadata de Managed Identity y lo usa directamente, sin ningún secreto en la configuración de la aplicación. En el entorno local de cada desarrollador, la misma línea de código cae en la autenticación vía Azure CLI (az login), siempre que esa persona tenga permisos RBAC asignados sobre el Key Vault de desarrollo. Esto tiene una consecuencia práctica que conviene anticipar: cada desarrollador necesita su propio permiso RBAC sobre los recursos de desarrollo, no basta con que la aplicación tenga permisos en producción. Cuando alguien nuevo se une al equipo y su entorno local falla con un error de autorización contra Key Vault, casi siempre es esto, no un problema del código.

Los errores de RBAC que aparecen siempre

El error más común no es de autenticación sino de autorización: la identidad se autentica correctamente contra Azure AD y obtiene un token válido, pero el recurso de destino responde 403 Forbidden porque nadie le asignó el rol RBAC necesario sobre ese recurso específico. Habilitar Managed Identity en un App Service no le da ningún permiso por sí solo; solo crea la identidad. El permiso es un paso aparte, y es el paso que más se olvida:

az role assignment create \
  --assignee <principalId-de-la-managed-identity> \
  --role "Key Vault Secrets User" \
  --scope /subscriptions/.../resourceGroups/prod-rg/providers/Microsoft.KeyVault/vaults/kv-pedidos-prod

Un segundo error frecuente es asignar el rol al clientId de la identidad en lugar de al principalId (objectId): son dos valores distintos aunque ambos aparezcan en la salida de az identity show, y usar el que no corresponde produce un error de "principal no encontrado" al crear la asignación, así que al menos se detecta rápido.

El tercero es de propagación, no de configuración: una asignación de rol RBAC recién creada puede tardar unos minutos en propagarse por Azure AD antes de que el token de la identidad refleje el nuevo permiso. Un pipeline que asigna el rol y segundos después intenta usar el recurso protegido puede fallar con 403 de forma intermitente, no porque la configuración esté mal sino porque todavía no se propagó. La solución no es asumir que el rol está mal asignado, sino esperar un margen razonable o separar la asignación de permisos del despliegue que los consume.

El cuarto, específico de Key Vault, es confundir el modelo de acceso heredado (access policies) con RBAC. Un Key Vault puede estar configurado para usar cualquiera de los dos modelos, y asignar un rol RBAC sobre un vault que todavía usa access policies no tiene ningún efecto: la identidad seguirá recibiendo 403 hasta que alguien migre el vault al modelo de permisos de Azure RBAC o agregue la identidad como access policy explícita. Vale la pena confirmar con az keyvault show cuál de los dos modelos tiene activo el vault antes de depurar el rol asignado.

El caso particular de AKS

En un cluster de AKS, la identidad administrada del nodo (la que usa el propio cluster para interactuar con el balanceador de carga o el disco administrado) es distinta de la identidad que un pod necesita para acceder a Key Vault o Storage. Usar la identidad del nodo directamente desde un pod expondría esos permisos a cualquier otro pod que corra en el mismo nodo, rompiendo el aislamiento esperado entre cargas de trabajo distintas dentro del mismo cluster.

La solución actual es Workload Identity Federation: se crea una identidad asignada por el usuario, se configura una federación de credenciales entre esa identidad y una service account de Kubernetes específica, y solo los pods que usan esa service account —identificada por su namespace y su nombre— pueden obtener tokens con esa identidad. Dos pods en el mismo nodo, con service accounts distintas, terminan con acceso a recursos de Azure completamente distintos, el aislamiento que la identidad del nodo por sí sola no puede dar.

Lo que sigue quedando fuera

Managed Identity no elimina la necesidad de pensar en secretos, solo reduce el número de lugares donde un secreto real tiene que existir. Las credenciales hacia servicios fuera de Azure y cualquier dato sensible que no sea en sí mismo un recurso de Azure siguen necesitando un mecanismo explícito de gestión de secretos, con Key Vault como pieza central y Managed Identity como el mecanismo para llegar hasta ahí sin agregar un secreto más a la cadena.

azure managed-identity rbac devops
← Volver al blog