En la anterior entrada os hablamos de la arquitectura de microservicios, explicando las razones y beneficios por los que muchos desarrolladores y negocios están optando por esta opción cuando se enfrentan al reto de crear una aplicación.
La aparición de esta arquitectura responde a la necesidad de desacoplar aplicaciones monolíticas, cuyo mantenimiento y escalabilidad se torna muy difícil. A medida que la complejidad de los problemas a solucionar aumenta, las aplicaciones monolíticas presentan problemas a nivel de rendimiento y tolerancia a fallos. Así, dividiendo aplicaciones monógamas en unidades independientes y significativamente más pequeñas se pueden resolver estos problemas.
Además, uno de los objetivos del uso de los microservicios pasa por ofrecer una mayor agilidad, calidad y eficiencia en la entrega y despliegue continuos del software, para así mejorar el llamado “time-to-market”.
Pero, ¿qué pasa con la seguridad?
Dividir las aplicaciones en un número mayor de componentes también aumenta la complejidad y dificultad para asegurar estos: problemas de comunicación entre servicios, al tener una gestión descentralizada de los datos puede existir una fragmentación de la consistencia de los datos y, por último, las superficies de ataque aumentan.
¡Tranquilo! Aunque las aplicaciones basadas en microservicios requieren de una protección más estratificada que las monolíticas, siguiendo los consejos y prácticas que te proporcionamos a continuación te garantizarán una defensa eficaz.
1. Integrar la seguridad desde el principio del desarrollo
Puede parecer obvio, pero es muy importante que, antes de comenzar a diseñar y desarrollar una nueva aplicación basada en microservicios, tomes conciencia sobre algunos aspectos que tienen que ver la seguridad a nivel global. Por ejemplo, debemos decidir qué protocolos de seguridad implementar a la hora de acceder a los recursos y quién estará autorizado o no. De esta manera, también evitaremos posteriores limitaciones a la hora de implementar nuevas features al software.
2. Validar los accesos de los usuarios mediante 2FA o tokens de un solo uso
Securizar todos los accesos a los recursos que se publican dificulta la entrada a los microservicios a aquellos atacantes que intenten entrar con credenciales robadas. En el caso de un portal web, aplica la autenticación de doble factor (Two-Factor Authentication) y en el caso de las API, hazlo mediante tokens con fecha de expiración.
No olvides seguir una estricta política de offboardings para que, en caso de que una persona abandone tu empresa, no siga teniendo acceso a los recursos en cuestión.
3. Monitorizar y crear alertas de uso y loggin externo
La monitorización siempre es una herramienta fundamental en cualquier infraestructura. No solo te permite tener una visión real de su rendimiento y estado, sino que también nos permite detectar comportamientos anómalos que predicen un ataque no deseado y que podremos abordar antes de que sucedan.
Para reforzarlo, podemos transferir los logs de una aplicación a un servicio externo, como por ejemplo el conocido Elasticsearch. Esto nos permitirá obtener un análisis más detallado sobre ese posible ataque que hemos detectado, en qué consiste o como nos afecta. Incluso podremos compararlo con comportamientos anteriores.
4. Mantener al día las actualizaciones de los sistemas operativos y aplicaciones o servicios que tengamos corriendo en nuestros hosts
Como en cualquier sistema, es importante mantener al día las actualizaciones de seguridad que van lanzando los creadores de los sistemas operativos o aplicaciones y servicios que estén corriendo en nuestros hosts, para evitar posteriormente el uso de exploits conocidos en la red en nuestra contra.
Especial hincapié en las aplicaciones de contenedores (como Kubernetes), que posteriormente limitarán el acceso a los recursos que alojan junto con los dispositivos de red.
5. Ejecutar imágenes propias o de fuentes confiables
Las aplicaciones de microservicios suelen utilizar contenedores para la implementación. Estos se basan en imágenes, que pueden ser de terceros y no estar libres de vulnerabilidades o de código malicioso. Asegúrate de que la fuente sea confiable.
En caso de usar imágenes propias, no olvides actualizarlas cuando convenga y no quedarse con una versión anterior de la imagen base usada.
6. Utiliza herramientas scanner de contenedores
El punto anterior nos lleva irremediablemente a este. Si has optados por los contenedores listos para usar, dispones de herramientas como Trivy (de Aqua Security) y Snyk, que escanean contendores, IaC como Terraform e, incluso Kubernetes, que permiten integraciones en Github Actions.
Una de las ventajas de poder integrar este tipo de scaners en nuetros CI/CD es que de manera automatizada tendremos un seguimiento de los fallos de seguridad y vulnerabilidades que se desplieguen en entornos altos como puede ser producción.
7. Exponer solo los servicios necesarios y por los puertos necesarios
Limita al máximo posible los elementos expuestos a Internet, de modo que solo se publiquen los microservicios imprescindibles (Frontend, API Gateway, etc), dejando restringidas las bases de datos, el Backend y el core de la aplicación.
8. Protege la red de accesos innecesarios
Tanto como si trabajas con una infrastuctura On Premise como si estás en el Cloud, es importante garantizar la protección a nivel de red. Las mejores prácticas pasan por limitar el acceso a los recursos usando listas blancas (whitelist) de IP públicas de confianza o de atacantes, limitando el acceso mediante acceso VPN y sólo por los puertos necesarios para que la aplicación funcione. Estos puertos se deben ir cambiando, evitando usar los por defecto de cada protocolo y añadiendo una capa más de seguridad a todo el conjunto.
9. Gestiona secretos en las pipelines de CI/CD
Las pipelines suelen contener información sensible de nuestra aplicación, como contraseñas o tokens, que debe cifrarse mediante external secrets, como AWS Secrets Manager o HashiCorp Vault.
También es fundamental limitar el acceso y modificación de pipelines, evitando usar un usuario con muchos privilegios para poder hacer el deploy de las nuevas versiones o los rollbacks en caso necesario.
10. Contenedores en modo Rootless para mitigar escaladas de privilegios
De ese modo, en caso de que exista una falla de seguridad y alguien consiga hacer login en un contenedor, evitaremos que el atacante se haga con el control total y reduciremos el alcance de las posibles consecuencias.
Podríamos seguir y hacer un listado MUY largo. De hecho, ¿qué otras prácticas crees que deberían estar en esta lista?