Skip to main content

Entonces, ¿crees que tu entorno de CI/CD es seguro?

Escrito por

Anita Buehrle

21 de febrero de 2019

0 minutos de lectura

Esta publicación, escrita en colaboración por Weaveworks y Snyk, explica cómo una canalización de integración continua (CI)/entrega continua (CD) basada en GitOps, combinada con buenas prácticas de seguridad, mejora la seguridad general de tu flujo de trabajo de desarrollo para Kubernetes.

La canalización de CI/CD habitual

Tu canalización de CI/CD podría parecerse mucho al modelo simplificado que aparece a continuación. El flujo comienza en el extremo izquierdo, cuando el código está en la máquina del desarrollador y se envía a un repositorio de código, como GitHub. Luego, una herramienta de CI obtiene el código, ejecuta pruebas y crea un artefacto, como una imagen de contenedor. La imagen se envía al repositorio de imágenes y se implementa en un orquestador de código abierto, como Kubernetes u otro sistema similar.

Diagrama del flujo de trabajo que muestra el recorrido de Dev por el repositorio de código, CI y el repositorio de imágenes hasta Kubernetes.

Pero a menudo se pasa por alto una cuestión: ¿es seguro el modelo habitual de envío de CI/CD? Considera estas dos preguntas:

  • ¿Tu entorno de CI tiene acceso directo al repositorio de imágenes de contenedores?

  • ¿Tu entorno de CI tiene acceso directo al clúster de producción?

Volvamos a ver la canalización, pero esta vez nos enfocaremos en qué etapas tienen acceso entre sí. En la imagen de abajo, usamos RW para el acceso de lectura y escritura, y RO para el acceso de solo lectura. ¡Probablemente hay muchas más líneas rojas de las que esperabas! Esta sencilla canalización infringe algunos de los principios de seguridad de Open Web Application Security Project (OWASP), incluido el principio de mínimo privilegio y la separación de funciones. Por ejemplo, el desarrollador tiene acceso de lectura y escritura al repositorio de código y al clúster.

Al eliminar el acceso directo de los desarrolladores al repositorio de imágenes y al clúster, se reduce al mínimo la superficie de ataque y el acceso privilegiado, y se separan las funciones.

Diagrama del flujo de trabajo que muestra Dev, repositorio de código, CI, repositorio de imágenes y clúster conectados mediante flechas de lectura y escritura y de solo lectura.

Entra GitOps

GitOps es una forma de hacer entrega continua para aplicaciones nativas de la nube. Funciona mediante Git como fuente de verdad para la infraestructura y las aplicaciones declarativas. Las canalizaciones de entrega implementan automáticamente los cambios en tu infraestructura cuando se realizan cambios en Git. Pero la idea va más allá: también usa herramientas para observar el estado real de producción y avisarte cuando la fuente no coincide con la realidad.

El método GitOps resuelve el problema de una canalización insegura mediante la ejecución de un operador de reconciliación desde el propio clúster. Este opera en un repositorio Git de configuración con credenciales independientes. El operador compara y reconcilia el estado deseado, expresado en los archivos de manifiesto almacenados en el repositorio Git, con el estado real del clúster.

Diagrama del flujo de trabajo que muestra a un desarrollador, un repositorio de código, CI, un repositorio de imágenes, un operador de clúster y un repositorio de configuración conectados mediante flujos de lectura y escritura y de solo lectura

Esto significa que no hay filtración de credenciales entre los límites. El sistema de CI puede operar en una «zona» de seguridad distinta, en lugar de hacerlo en el clúster de destino. Cada componente de la canalización necesita una sola credencial RW. Como las credenciales del clúster nunca salen del propio clúster, ahora puedes «mantener tus secretos cerca».

¿Ya no tengo que preocuparme por la seguridad?

Al adoptar este enfoque, reduces el riesgo de seguridad al resolver, entre otros problemas, los relacionados con el principio de mínimo privilegio y la separación de funciones. Por supuesto, esto no resuelve todos tus problemas de seguridad. De hecho, pone aún más énfasis en la necesidad de proteger bien tu repositorio de código.

Entra GitSecOps

Está bien, ya tenemos suficientes palabras de moda en nuestra industria, así que no inventemos otra. Dicho esto, la mayoría de las cosas que dice James Governor, también conocido como @monkchips, tienden a hacerse realidad tarde o temprano. ¡Gracias por la idea, James! Esperamos que te guste la publicación.

Aquí tienes algunos consejos para proteger mejor tu repositorio de código.

Agrega pruebas de seguridad a tus PRs

Todos los principales repositorios de código cuentan con potentes marcos de trabajo basados en eventos que permiten enviar solicitudes HTTP POST al servicio que elijas cuando se activan eventos. Puedes elegir entre una gran variedad de eventos, pero uno de los más útiles para probar los cambios incrementales en tu código es el evento pull_request.

Muchas herramientas de análisis estático de código admiten hooks para que, cuando se crea un PR, se envíe una solicitud HTTP POST que te pida probar las actualizaciones más recientes. También es un buen momento para asegurarte de que los cambios en el código y la configuración cumplan con tus expectativas de seguridad.

Analiza tu repositorio estáticamente con Snyk

Snyk analiza estáticamente tu repositorio para encontrar las dependencias vulnerables que podrías estar usando y te ayuda a corregirlas. Puedes probar tus repositorios desde la interfaz de Snyk para encontrar problemas, pero también puedes evitar que los usuarios agreguen nuevas bibliotecas vulnerables mediante pruebas en los pull request y el rechazo de una prueba si se introduce una nueva vulnerabilidad.

El panel de estado muestra una verificación de seguridad de dependencias fallida con dos problemas nuevos, mientras que la rama no tiene conflictos de fusión.

Además de la integración práctica con GitHub, GitLab y Bitbucket, los pull request son mejores que «romper la compilación». De hecho, ni siquiera tienen que bloquear una fusión, ya que por defecto solo proporcionan información. Las pruebas se enfocan únicamente en tus cambios, no en el resultado general, y solo fallan si introdujiste una biblioteca vulnerable, no si ya existía antes de tu cambio.

Nunca almacenes credenciales como código o configuración

Una búsqueda rápida en GitHub muestra lo extendido que está el problema de las contraseñas almacenadas en repositorios. Los 350.000 commits que aparecen en esta búsqueda sencilla no incluyen los que no eran tan obvios por sus mensajes de commit, ni aquellos en los que se intentó encubrir el rastro eliminando el historial.

También puedes usar herramientas como git-secrets para interrumpir activamente las compilaciones cuando se encuentre información confidencial en el código o en un archivo de configuración. Establecer reglas para todo el equipo que eviten que esto ocurra es una excelente manera de prevenir malas prácticas en el flujo de trabajo actual de los desarrolladores.

Hay muchas formas de evitar incluir credenciales en tu repositorio desde el principio. Intenta implementar todas las que puedas, pero incluso así siempre existe la posibilidad de que se filtre información confidencial. También deberías considerar auditar tus repositorios con regularidad y usar herramientas como GitRob o truffleHog, que analizan tu base de código en busca de información confidencial mediante la búsqueda de patrones.

Si descubres que almacenaste datos confidenciales en tu repositorio de código, tendrás que hacer varias cosas para resolverlo:

  1. Tendrás que invalidar los tokens y las contraseñas que quedaron expuestos.

  2. Una vez que un secreto se hace público en internet, debes asumir que está en manos de atacantes y actuar en consecuencia.

  3. Elimina todo rastro de tus secretos del historial para asegurarte de que no queden en el código ni en el registro de auditoría.

Controla estrictamente el acceso

Exige a tus colaboradores que sigan estas prácticas básicas:

  • Exige la autenticación de dos factores en las cuentas de GitHub de todos los colaboradores.

  • Nunca permitas que los usuarios compartan cuentas o contraseñas.

  • Protege adecuadamente todas las computadoras portátiles y dispositivos que tengan acceso a tu código fuente.

  • Las cuentas suelen ser personales y no desaparecen automáticamente cuando los usuarios dejan la empresa. Asegúrate de revocar diligentemente el acceso de quienes ya no trabajan contigo.

  • Los administradores del repositorio deben gestionar el acceso del equipo a los datos. Da a los colaboradores acceso únicamente a los datos que necesitan para hacer su trabajo.

Agrega un archivo SECURITY.md

Es natural que la mayoría de los propietarios y encargados del mantenimiento de proyectos agreguen un archivo README.md a su repositorio. De hecho, hoy en día está bastante mal visto que falte el README. Del mismo modo, cada vez es más común agregar un archivo SECURITY.md que destaque la información de seguridad del proyecto. Este archivo no solo proporciona a los usuarios información de seguridad importante, sino que también obliga a los encargados del mantenimiento a pensar cómo gestionar las divulgaciones de vulnerabilidades, las actualizaciones y las prácticas generales de seguridad. Puedes encontrar buenos ejemplos de archivos SECURITY.md en los repositorios de Apache Storm y TensorFlow.

Resumen

Tu servidor de CI puede coordinar sin problemas el desarrollo, la fusión en la rama principal, la compilación y las pruebas. Sin embargo, surgen otras consideraciones de seguridad cuando los servidores de CI empiezan a realizar operaciones de entrega continua. GitOps se basa en Kubernetes o en el clúster para gestionar internamente las implementaciones a partir de las actualizaciones de la rama principal. Esto también se conoce como el «modelo pull para CD».

Git es la única fuente de verdad para el código, así como para la configuración y la pila asociada. Esto lo convierte en un foco de seguridad mucho más importante. Seguir buenas prácticas generales en tu repositorio de código puede ayudar de muchas maneras, por ejemplo, usando automáticamente herramientas de prueba como Snyk en cada pull request, creando un archivo SECURITY.MD que incluya procedimientos de seguridad establecidos y usando bóvedas para los secretos en lugar de almacenarlos en el código.

Para incorporar seguridad a tus flujos de trabajo de Git o a tus canalizaciones de CI/CD, prueba Snyk gratis. También puedes reservar una demo privada con nuestro equipo para ver Snyk en acción.