5 buenas prácticas para crear controles de acceso modernos para aplicaciones en la nube
15 de noviembre de 2022
0 minutos de lecturaHace poco, me reuní con Or Weis, Snyk Ambassador, para hablar sobre el control de acceso en la nube. Or es un emprendedor que vive en Tel Aviv, donde fundó Permit.io, una solución que permite a los desarrolladores incorporar permisos y controles de acceso en cualquier producto en cuestión de minutos y evita la frustración de tener que reconstruirlos constantemente.
En nuestra conversación, abordamos diversos temas, como:
Por qué es tan importante usar siempre controles de acceso modernos en la nube
Por qué RBAC no es suficiente
Seguridad y cumplimiento
Las distintas capas de control de acceso en la nube
La cascada de IAM
Reducir la superficie de ataque al crear controles de acceso
Además de todo esto, también hablamos sobre las mejores prácticas de control de acceso que puedes empezar a aplicar en tus aplicaciones en la nube. En esta publicación, repasaremos esas prácticas con información tomada directamente de la conversación completa. Para conocerlas con más detalle, te recomiendo ver la conversación completa:

5 buenas prácticas para controles de acceso modernos en la nube
Tanto si quieres crear controles de acceso por tu cuenta como si quieres hacerlo con herramientas de código abierto o propietarias, estas son cinco buenas prácticas para garantizar que lo que desarrolles sea a prueba de futuro y resistente a errores, y que proporcione medidas de protección para estabilizar y proteger tu sistema.
Desacopla el código de las políticas
Diseña para actualizaciones basadas en eventos (desacopla los datos del código)
Diseña un back office para las partes interesadas
Crea una interfaz para los clientes
Implementa GitOps
1. Desacopla el código de las políticas
La primera y probablemente más importante buena práctica es desacoplar las políticas del código. A menudo vemos que las personas incorporan la lógica de autorización directamente en la lógica de la aplicación. Al final, el resultado es un código enredado, con condiciones «if» que consultan tanto la base de datos como otras fuentes para obtener la lógica de autorización y, al mismo tiempo, consultan la lógica de la aplicación. Con el tiempo, ambas suelen terminar mezclándose. Así que, cuando los desarrolladores agregan nuevas condiciones, resulta casi imposible entender qué partes de la condición «if» corresponden a la autorización y cuáles a la aplicación.
El resultado es que, cuando quieres actualizar la capa de autorización o la propia aplicación, tienes que revisar todo línea por línea y refactorizarlo, lo que nos lleva al doloroso mundo de la refactorización. Por eso, lo que queremos es desacoplar las políticas del código. Queremos adoptar políticas como código (PaC) y gestionar ese código por separado, idealmente como un microservicio independiente que los demás componentes de la aplicación puedan consultar para obtener la lógica que necesitan.
Es posible que un desarrollador que recién empieza en este campo se haga estas preguntas:
¿Quién controla el acceso a ese servicio?
¿Qué va primero: la autenticación o la aplicación?
Para decirlo sin rodeos, este es un mundo de complejidad enorme y muy recursivo, llamado autorización para la autorización. En pocas palabras, puedes minimizar el control de acceso de la capa siguiente y, muchas veces, reducirlo exclusivamente a la autenticación. Así, cuando tus microservicios se conectan al microservicio de autorización, pueden hacerlo simplemente porque tienen una identidad que ese microservicio verifica. Las capas hacen que todo sea más complejo, pero la mayoría de las herramientas intentan resolverlo por ti o, al menos, asumir una parte importante de esa carga.
Recuerda que, idealmente, queremos crear un microservicio independiente para la autorización. No hace falta que sea perfecto. Al principio, puede ser tan simple como una función que siempre devuelve «true». Y, aunque no queramos construir todo desde el primer día, sí queremos contar con marcadores de posición bien conectados para poder actualizarlos gradualmente a medida que surjan nuevos requisitos. Ya sea una función Lambda, un contenedor pequeño o lo que prefieras, debe ser algo que pueda evolucionar por separado y que puedas refactorizar fácilmente cuando surjan requisitos adicionales.
2. Diseña para actualizaciones basadas en eventos (desacopla los datos del código)
La segunda buena práctica es adoptar un enfoque basado en eventos. Los sistemas complejos tienen políticas complejas que cambian junto con la superficie de la aplicación. Si diseñas tu aplicación desde el principio para que se base en eventos, será más fácil gestionar las actualizaciones futuras.
Veamos un ejemplo. Imagina que quieres una política sencilla, como esta: Solo los usuarios que pagaron por una función pueden usarla. Esa información ya no está en tu base de datos ni forma parte de tu aplicación. Está en un servicio de terceros, como Stripe, Chargebee o PayPal. Por eso, queremos poder propagar en tiempo real la información de esos servicios a medida que cambia, y hacer que influya en nuestra capa de autorización.
La mejor manera de hacerlo es adoptar un enfoque basado en eventos. En esencia, esto significa poder recibir webhooks de esos servicios o componentes externos y propagarlos a nuestra capa de autorización. Esto se llama «desacoplar los datos del código» y es tan importante como desacoplar las políticas del código.
3. Back office para las partes interesadas y 4. Interfaz para los clientes
Sabemos que tendremos clientes y otras partes interesadas (como un gerente de producto, empresas de seguridad, etc.) y que querrán contar con interfaces para gestionar el control de acceso. Aunque no tenemos que crear esas interfaces desde el primer día, debemos estar preparados para crearlas y ofrecerlas a medida que surjan los requisitos.
Queremos tener un back office donde las distintas partes interesadas puedan gestionar la aplicación y ofrecer interfaces a los propios clientes para que puedan invitar usuarios, asignar roles e incluso configurar políticas por su cuenta. Como coincidiría la mayoría de los ingenieros, el mejor servicio es el autoservicio.
5. Implementa GitOps
Por último, y esto nos lleva de nuevo a las políticas como código, simplifica la seguridad con GitOps. Hablamos de gestionar reglas e instrucciones complejas en un entorno en constante cambio y con muchas partes interesadas. La mejor manera de hacerlo es mediante código. Así como usamos infraestructura como código y seguridad como código, también deberíamos usar políticas como código.
Si gestionas las políticas como código independiente (idealmente con un framework adecuado) en un repositorio de Git, puedes administrar fácilmente las versiones, las pruebas, las evaluaciones comparativas y las revisiones de código. Así, no tienes que reinventar la rueda para gestionar las políticas ni para conectarlas con tu sistema.
Mantente siempre al día
Ten presentes estas cinco buenas prácticas cuando empieces a crear algo. Solo con saber que estos aspectos surgirán más adelante, puedes ahorrarte meses de refactorización.
Por último, muchas gracias a Or Weis por conversar conmigo y compartir su experiencia sobre este tema. Si tienes preguntas, te recomendamos contactar a Or Weis en Twitter o LinkedIn, o unirte al Discord de la comunidad DevSecCon y preguntarle directamente.
Empieza con Capture the Flag
Aprende a resolver desafíos de Capture the Flag viendo nuestro taller virtual introductorio a pedido.
