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:

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

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

Seguridad, palabrita omnipresente en este mundo tecnológico pero que tantas confusiones trae a quienes de alguna manera tienen que lidiar con ella, ya sea estableciendo infraestructuras seguras, o desarrollando aplicaciones que no sean vulnerables a malos usos o ataques, y claro… con la nube hay cosas que toca revisitar, y … a eso vamos.

Este articulo no pretende ser una guía de como implementar la seguridad en Azure, pero si que espera contextualizar el entorno en que nos encontramos, como hemos llegado hasta el y una (entre otras) forma adecuada de gestionar la seguridad de nuestras aplicaciones en la nube.

En todo caso tenemos que partir de dos conceptos esenciales (otros son los relativos a la categorización de los recursos a proteger) en este rubro: Autenticación y Autorización.

Grosso modo, Autenticación es la capacidad de garantizar que quien quiere acceder a un recurso (sistema, dato, infraestructura) es quien dice ser, y esto se ha ido logrando mediante: contraseñas, biometría, tokens físicos, etc. Por otro lodo la Autorización se enfoca en la asignación correcta de los permisos respecto a que se puede hacer con el recurso en cuestión, dependiendo del rol o perfil de la persona ya Autenticada.

Hasta ahí todo claro, ahora reflexionemos como hemos trabajado con estos conceptos, supongamos que tenemos una BD llamada “Negocios” con dos tablas: “Productos” y “Ventas”, y supongamos que se necesita que Juan, pueda mantener el catálogo pero que solo pueda consultar las ventas realizadas, empecemos poco a poco.

Pues bien, para esto será necesario que Juan se autentique ante la BD, ya sea mediante usuario y password manejados por la BD, o que la BD “acepte” la autenticación que Juan ha hecho ante el Sistema Operativo, ya sea local o el de la organización, y por otro lado aplicar un GRANT al usuario “Juan” para que este solo puede hacer SELECT sobre la tabla “Ventas”, y además un GRANT para que este mismo usuario pueda hacer INSERT, SELECT, UPDATE y DELETE sobre “Productos”, pero no permisos para borrar la tabla o modificar su estructura, hasta aquí nada fuera de lo común, y con la misma lógica podríamos dar GRANT más generosos a Elena para que haga operaciones de mantenimiento sobre ambas tablas.

Esto de manera muy simplificada, en un entorno real y mas ordenado, lo usual es que se creen “roles” preestablecidos con las diversas combinaciones de permisos y de esta manera a Juan se le podría asignar un rol ya existente que tenga los permisos ya mencionados sobre “Ventas” y “Productos” (en este caso Rol1), siendo que luego a alguien nuevo se le asigne ese mismo Rol1, simplificando la administración en lugar de asignar los permisos de manera individual, como se ve aquí:

Permisos y roles sobre BD Finish Reading: Conociendo los modelos de seguridad en la nube con Managed Identities (I)

Viendo la seguridad de la configuración con Azure KeyVault, .Net Core y Azure DevOps

Por aquí ya hemos hablado una vez y otra sobre como gestionar los datos sensibles (como las cadenas de conexión) de nuestras aplicaciones, porque, claro, nadie debería de poner los datos de producción en el código fuente que grabamos en nuestro repo, ¿verdad?

Anteriormente las opciones pasaban por efectuar mezclas/transformaciones de tal manera que en tiempo de compilación se generara un archivo final con los datos sensibles correspondientes a cada entorno, lo cual si bien nos daba simplificación para colocar la clave correcta en el paquete y entorno correcto, nos obligaba a seguir versionando las cadenas de conexión en el código fuente (por no mencionar que había que compilar mas de una vez); la otra opción pasaba por gestionar dentro del entorno de destino (en nuestros ejemplos: WebApps) sobrescribiendo de esta manera los valores que vinieran desde el código fuente.

Dado que ni nuestro repositorio ni nuestra herramienta de integración/despliegue deberían contener datos sensibles, usaremos un servicio de nube que nos da la seguridad necesaria para gestionar nuestras credenciales, el Azure KeyVault, el cual nos permite almacenar de manera segura y granular ya sea certificados digitales como data sensible, pudiendo restringir quienes pueden acceder a que datos y a que no (aplicando Control de acceso basado en roles: RBAC). Un mecanismo usual de accesos a estos recursos sensibles es programar dentro de nuestra aplicación un código que lea los valores en tiempo de ejecución (procurando no releer el valor a cada uso, sino hacerlo una única vez), en este caso usaremos un enfoque distinto que consistirá en leer los valores almacenados en KeyVault durante nuestro pipeline de despliegue, alterando secciones del archivo appsettings.json (porque nuestro ejemplo se basara en .Net Core) que se alojara en nuestra Web App destino (aunque también funciona perfectamente en un despliegue sobre IIS).

Así que estos serán los pasos que seguiremos:

  • Crear un KeyVault
  • Crear un «Secret» dentro de nuestro KeyVault, ahí sera donde almacenaremos una cadena de conexión a la base de datos
  • Identificar el «Principal» mediante el cual nuestro Team Project se conecta a Azure
  • Dar los permisos sobre nuestro KeyVault a dicho principal
  • Identificar en nuestra aplicación las secciones a modificar en tiempo de ejecución
  • Enlazar nuestro TeamProject contra el KeyVault, fijando el scope respectivo
  • Configurar el reemplazo de valores en el appsettings.json
  • Validar que nuestros cambios han sido desplegados en el entorno destino

Para esta demo asumiremos que tendremos tanto un pipeline de Build como de Release, de una aplicación en ASP.Net Core, en nuestro ejemplo usare la aplicación de ejemplo del libro de EF Core in Action (excelente libro que tuve el honor de revisar) cuyo código fuente se puede descargar aquí, y claro, como es usual el despliegue lo haremos contra una Azure Web App.

Para el primer paso seguiremos las instrucciones dadas en la primera parte de este articulo, en mi caso he usado estos nombres: RG_DevmoVault01 para el Resource Group y ErnestoDemoKeyVault para el KeyVault, como en este caso la creación la hemos hecho vía linea de comandos verificaremos que podemos revisar este recurso en el Portal de Azure, así:

Finish Reading: Viendo la seguridad de la configuración con Azure KeyVault, .Net Core y Azure DevOps