Conociendo los modelos de seguridad en la nube con Managed Identities (y II)

En el artículo anterior revisamos las bases del nuevo concepto de seguridad en la nube, recursos identificados a los que se les da autorización sobre otros recursos, y… eso ¿Cómo se implementa? Pues lo usual hasta hace pocos meses ha sido trabajar con los llamados “Service Principal”, los cuales la verdad (como lo pudimos comprobar en un post previo) son bastante engorrosos de utilizar, hay que crearlos explícitamente (aunque algunos se crean automáticamente tras bastidores) y mediante estas entidades es que se pueden manejar la asignación de permisos entre recursos.

Llegado este momento toca presentar a las Managed Identities, en las que básicamente como desarrolladores se nos permite asumir que los diversos recursos de Azure cuentan con identidades de pleno derecho, casi casi como si fueran usuarios humanos, para empezar veamos como nos lo propone Microsoft:

Ok ¿y esto como se entiende? Para hacer las cosas más simples definamos un servicio “Consumidor”, que podría ser una Web App o un Azure Functions, y un servicio “Objetivo” que podría ser un Azure SQL Database o para este ejemplo un App Configuration.

Con esto en mente, primero debemos habilitar al servicio “Consumidor” (para nuestro ejemplo un Azure Function) para que sea identificable en el ecosistema de nuestro Azure AD, y esto es debido a que los recursos en Azure no “nacen” con el “Managed Identities” habilitado, así que solo tenemos que ir al Portal de Azure y activar la opción respectiva sobre nuestra Function, simple, ¿no?

Hecho esto, el recurso “Objetivo” debe asignarle un permiso al “Consumidor”, y ojo a esto… los recursos pueden ser diversos y de distintos niveles, por ejemplo, si hablamos de un Storage Account yo podría dar un permiso, digamos de lectura, sobre todos los containers conformantes a un Logic App, pero si quisiera ese permiso podría ser solo por UN container… bueno, prosigamos.

En el Portal nos vamos al App Configuration (nuestro recurso “Objetivo”) y elegimos Access control (IAM), lo cual nos llevara a un blade donde podremos ver los accesos concedidos actualmente, pero en este momento le daremos clic a “Add”.

Y aquí eligiremos “Add role assignment”.
Aprovecho para indicar dos detalles, este blade de Access control (IAM) es similar en todos los recursos de Azure que soporte Managed Identities, por lo que los pasos que estamos viendo son equivalentes en otros recursos, y por otro lado… Microsoft esta habilitando una nueva UX para la asignación de roles (como podemos ver) pero como esta opción esta sujeta a cambios no la cubriremos de momento.

En este punto lo que debemos hacer es elegir que ROL deseamos asignar al recurso Consumidor, y como podemos ver hay muchos (y varian segun el tipo de servicio), en este caso tratando de un App Configuration voy a elegir App Configuration Data Reader el cual permitirá que desde nuestro Functions podamos acceder a los valores almacenados en el AppConfiguration, pero no modificar dichos valores (para eso usaríamos p. ej App Configuration Data Owner), en ese sentido hay que ser bien preciso respecto a los roles que otorgar según nuestra necesidad.

Ok, ya hemos elegido el Rol (con los permisos inherentes) así que ahora toca elegir a que recurso consumidor lo asignamos, y como podemos ver tenemos la opción de asignarlo a una persona, pero en nuestro caso queremos asociarlo a un Azure Functions, así que elegimos esa opción.

Y ahora toca elegir el Azure Functions en concreto al cual asignar el rol, primero elegimos la subscripción y así tendremos las opciones disponibles (en nuestro caso las Azure Functions con el Managed Identity previamente activada):

El ultimo paso es sencillo, seleccionamos el Function respectivo y grabamos…

Cabe mencionar que esto se puede realizar mediante el uso de Azure CLI, pero aquí hemos optado por el modo gráfico para hacer mas explicita las relaciones entre servicios que queremos construir.

Ok, ya tenemos asignado un permiso al recurso, pero… ¿qué ganamos con esto? Bueno recordemos un poco.

Ya tenemos claro que las cadenas de conexión NO deben almacenarse como parte del código fuente, tanto por razones de seguridad como para facilitar desplegar el mismo artefacto en distintos entornos, por lo cual es el entorno (en el caso de Functions eso es parte del App Settings) quien debería pasarnos esa cadena de conexión, así que si no usáramos las Managed Identities que acabamos de configurar deberiamos usar la cadena de conexión tal cual la provee el propio servicio App Configuration:

Si, con clave incluida, todo mal, por lo que todo aquel que tenga acceso al entorno podría husmear la clave, pero al usar Managed Identities nuestra cadena de conexión luce así:

Solo sabemos hacia donde se conecta la aplicación “Consumidora”, pero no tendremos la clave que nos sirva para acceder a ese recurso. Potente ¿no?

Ahora bien, recordemos el gráfico del post pasado:

Permisos y roles sobre BDEn ese esquema usábamos un esquema de Roles para que lo que pueda hacer Juan sea diferente de lo que puede hacer Elena, nada fuera de lo común, pues bien (como hemos estado insistiendo), al avanzar en los permisos en la nube, los recursos/servicios pasan a ser manejados casi casi como si fueran… personas! ¿Cómo? Vamos a ello.

Supongamos que nuestro ejemplo de Functions y App Configuration evoluciona, y necesitáramos tener una Azure Web App para dar “mantenimiento” a las claves/valor del App Configuration sin pasar por el portal o CLI de Azure, y que aparte de ello, nuestras Functions tuvieran que leer Secretos almacenados en un Key Vault, pues para ello solo necesitaríamos:

  • Que la Web App active el uso de Managed Identities
  • Asignarle a esta Web el Rol App Configuration Data Owner
  • Agregar a las Functions el Rol Key Vault Secrets User

Con lo que tendríamos una distribución de roles así (nótese la semejanza con el gráfico de Juan y Elena):

Ahora si debe quedar claro nuestro recorrido: hemos evolucionado en la gestión de identidades y roles al pasar a la nube, mediante un concepto/enfoque conocido como RBAC (Role Based Access Control), y para implementar este concepto hemos usado las Managed Identities de Azure, interesante ¿no?.

En mi repo de GitHub les dejo un ejemplo basado en Azure Functions que permite conectarse a un App Configuration, a Key Vault y a Service Bus.

Upps mencione Service Bus, y esto amerita explicar algo muy particular que está vigente al momento de escribir este artículo.

Como mencione, esto de los Managed Identities es algo relativamente nuevo, que Microsoft está promocionando como el mecanismo de seguridad a usar, perooo no ha sido desplegado a todos los recursos y uno de los que aun está pendiente es Service Bus (otro es Static Web Apps como servicio “consumidor”), por lo que la cadena de conexión aún debe de lucir de esta forma.

Si queremos mantener seguridad sobre el acceso a Service Bus desde Azure Functions (y creo que desde Web Apps) deberemos usar la “sintaxis KeyVault”, lo cual significa que deberemos guardar las keys de nuestro Service Bus en un secreto de Key Vault y recuperarlo de esta manera:Este procedimiento tiene una limitación, y es que solo podemos usarlo en el nivel Premium, por lo que deberemos esperar a que Managed Identities se termine de desplegar en Service Bus a fin de poder lograr esta ventaja en nuestras aplicaciones al margen del tier que hayamos contratado, les ire informando al respecto.

Otra opción seria recuperar (desde Key Vault) la cadena de conexión en tiempo de ejecución, pero esto nos agregaría unos inconvenientes que debemos ponderar:

  • Esto no nos serviría para configurar “triggers” en Azure Functions
  • Añadiría complejidad adicional al código
  • Poner sobre la mesa las limitaciones de Azure KeyVault, en cuanto a numero de peticiones, y considerar las opciones para gestionarlas elegantemente

El caso de Service Bus nos hace recordar lo que comentábamos en el anterior post, de que a veces no hay mas remedio que usar passwords en las cadenas de conexión, pero que esto debería mantenerse controlado al máximo, salvo cuando no hay mas remedio, y claro debiendo extremar los cuidados y procedimientos de acceso a estos valores sensibles.

En todo caso, si quieren que les explique como usar Key Vault y el uso de la sintaxis KeyVault para acceder a secretos, me lo dejan en la caja de comentarios.

Bueno, este tema da para largo, pero espero que con esto tengamos claras las bases de como entender los modelos de roles de seguridad en la nube. especialmente en entornos cloud-native, y como empezar a aplicarlos mediante Managed Identities, espero que les haya sido de utilidad. De nuevo reitero que el reto de las organizaciones es entender y adoptar el nuevo modelo, poniéndose manos a la obra en definir su política de roles dentro de sus tenant en la nube.

Recomendado:
Use managed identities to access App Configuration

Agregue un comentario

Su dirección de correo no se hará público. Los campos requeridos están marcados *

Time limit is exhausted. Please reload the CAPTCHA.