¿Cómo escanear las vulnerabilidades de una imagen Docker en un pipeline de Gitlab con Cyberwatch?

Cyberwatch permite escanear las vulnerabilidades de una imagen Docker. Este proceso puede ser muy práctico al utilizarlo en un proceso de CI/CD, especialmente en un pipeline de GitLab, sobre todo en el marco de un enfoque DevSecOps.

En este artículo veremos:

  1. Cómo crear una imagen Docker a partir de un pipeline de GitLab;
  2. Cómo escanear estas imágenes en Cyberwatch.

Preámbulo: ¿por qué escanear las vulnerabilidades de una imagen Docker en un pipeline de GitLab DevSecOps?

¿Qué es un proceso de CI/CD?

Los equipos de desarrollo de software utilizan con frecuencia plataformas de forja para colaborar. Una plataforma de forja permite añadir una capa colaborativa más intuitiva sobre un sistema de control de versiones como Git o Mercurial. Las plataformas de forja más comunes ofrecen funcionalidades de seguimiento de errores, integración continua y entrega continua.

Estos dos últimos términos, integración y entrega continua, se conocen comúnmente por sus siglas en inglés CI/CD (Continuous Integration y Continuous Delivery).

Un proceso de CI/CD es, por tanto, un sistema de integración y entrega continua, es decir, un mecanismo donde cada nueva línea de código de un desarrollador se envía a un repositorio compartido y, posteriormente, activa pruebas de regresión y validación funcional (parte de integración continua o CI), así como etapas de despliegue automático en diferentes entornos (parte de entrega continua o CD).

Un proceso de CI/CD se implementa mediante etapas vinculadas entre sí para crear lo que se denomina un pipeline.

Los procesos de CI/CD son muy utilizados en los enfoques denominados «DevOps», donde las etapas de despliegue se automatizan mediante fragmentos de código.

En este artículo, nos centraremos en el caso de los pipelines de GitLab, una plataforma de forja de software libre muy utilizada, especialmente por su capacidad de ser desplegada en modo «autoalojado».

¿Por qué escanear las vulnerabilidades de una imagen Docker?

Un proceso de CI/CD puede generar entregables denominados artefactos de software. Un ejemplo clásico es la creación de imágenes Docker, construidas por el pipeline de CI/CD.

La producción automatizada de imágenes Docker permite, por ejemplo, disponer de una imagen Docker para cada nueva modificación realizada en el software desarrollado por un equipo, facilitando así el despliegue y la prueba de dichas modificaciones en entornos dedicados.

Sin embargo, una imagen de Docker contiene componentes que están sujetos a vulnerabilidades, al menos a aquellas registradas en las bases de datos CVE.

Estos componentes potencialmente vulnerables son, por ejemplo, los paquetes vinculados a la base del sistema de la imagen (como los paquetes DPKG instalados en una imagen de Docker Debian), los binarios desplegados dentro de dicha imagen, o incluso las bibliotecas de software utilizadas por los distintos lenguajes de programación (módulos PIP, GEM, NPM, PHAR, etc.).

Por lo tanto, toda imagen de Docker debe ser escaneada periódicamente en busca de vulnerabilidades para determinar los riesgos existentes y tomar las mejores decisiones al respecto.

Cuando se añaden etapas de seguridad en un enfoque DevOps, hablamos de «DevSecOps» para indicar que los pasos de verificación de seguridad informática también se comprueban automáticamente con cada modificación de un proyecto.

¿Por qué escanear una imagen de Docker en un proceso de CI/CD?

El objetivo principal de un proceso de CI/CD es mejorar la calidad del software desarrollado mediante la ejecución periódica de pruebas funcionales y de seguridad.

Una etapa muy conocida en CI/CD es el análisis estático de código, o SAST (Static Application Security Testing), que permite identificar errores potenciales introducidos en el código que podrían derivar en inyecciones SQL o XSS.

Otra etapa cada vez más utilizada en los procesos de CI/CD es el escaneo de vulnerabilidades, donde las imágenes de Docker generadas durante el proceso se analizan para autorizar o bloquear su puesta en producción.

Esto permite identificar de forma temprana la presencia de vulnerabilidades CVE en los componentes desplegados y corregirlas antes de que puedan afectar a los entornos de los clientes.

1) ¿Cómo escanear una imagen de Docker con Cyberwatch desde un pipeline de Gitlab?

1.a) Requisitos previos

Para conectar Cyberwatch a un pipeline de Gitlab y escanear las imágenes de Docker asociadas, necesitaremos lo siguiente:

  • Un motor de ejecución de Docker (es decir, una máquina con Docker Engine instalado);
  • Imágenes de Docker para recuperar desde un pipeline de Gitlab.

El pipeline de Gitlab controlará Cyberwatch mediante API para indicar qué imagen debe escanearse. Cyberwatch analizará dicha imagen desde el motor de ejecución de Docker y enviará los resultados al pipeline de Gitlab en formato Junit-XML.

1.b) Configurar el motor de ejecución de Docker para que sea accesible desde Cyberwatch

En primer lugar, configuraremos Docker para permitir las conexiones y las órdenes enviadas por Cyberwatch.

Para que estos procesos se realicen mediante una comunicación segura, necesitaremos los siguientes elementos:

  • Una autoridad de certificación, con su certificado;
  • Un certificado de cliente firmado por la autoridad de certificación;
  • Una clave privada asociada al certificado de cliente.

Generar el certificado de la autoridad de certificación

Para generar una autoridad de certificación y su certificado, ejecutaremos las siguientes líneas de comando.

openssl req -new -newkey rsa:4096 -nodes -sha256 -keyout cakey.pem -out cacert.pem \
-x509 -days 730 -subj '/CN=Docker CA for Cyberwatch'

Generar el certificado de cliente y la clave privada

Para generar la clave privada, introduciremos las siguientes líneas de comando:

openssl genrsa -out dockerdkey.pem 4096

A continuación, para generar el certificado de cliente, utilizaremos las líneas siguientes, sustituyendo <IP> por la dirección IP de la máquina Docker:

openssl req -new -key dockerdkey.pem -sha256 -out dockerdcsr.pem -subj '/CN=Docker daemon certificate for Cyberwatch'

openssl x509 -req -in dockerdcsr.pem -CA cacert.pem -CAkey cakey.pem -CAcreateserial -sha256 -out dockerdcert.pem \
-days 730 -extfile <(echo "subjectAltName = IP:<IP>" ; echo 'extendedKeyUsage = serverAuth')

Configurar el servicio DockerD para utilizar los certificados generados

Una vez generados los certificados, solo queda configurar DockerD para que utilice los certificados creados. Para ello, modificaremos el archivo /etc/docker/daemon.json añadiéndole los siguientes elementos:

{
   "hosts": ["unix:///var/run/docker.sock", "tcp://0.0.0.0:2376"],
   "tls": true,
   "tlsverify": true,
   "tlscacert": "$PWD/cacert.pem",
   "tlscert": "$PWD/dockerdcert.pem",
   "tlskey": "$PWD/dockerdkey.pem"
}

A continuación, es necesario reiniciar Docker para que la configuración surta efecto, utilizando los siguientes comandos:

systemctl daemon-reload
systemctl restart docker

2) ¿Cómo construir una imagen de Docker en un pipeline de Gitlab?

Para almacenar nuestras imágenes, utilizaremos Gitlab Container Registry, incluido de forma nativa en Gitlab desde la versión 8.8.

Gitlab Container Registry le permite probar, construir y desplegar sus proyectos a partir de una imagen de Docker creada directamente en Gitlab.

Para la demostración, podemos utilizar un archivo Dockerfile muy sencillo, basado en Nginx:

FROM nginx:alpine

Para subir esta imagen al registro de Gitlab mediante el pipeline, utilizamos el archivo .gitlab-ci.yml que aparece a continuación (sustituyendo <group>, <project> y <image> por los parámetros correspondientes a su proyecto de Gitlab):

stages:
   - build

docker-push:
 image: docker:latest
 stage: build
 services:
   - docker:dind
 before_script:
   - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
 script:
   - docker build --pull -t $CI_REGISTRY/<group>/<project>/<image>:latest .
   - docker push $CI_REGISTRY/<group>/<project>/<image>:latest

Esta configuración permite conectarse al registro de contenedores de GitLab, construir una imagen Docker a partir del Dockerfile anterior y enviarla al registro.

3) ¿Cómo escanear una imagen Docker con Cyberwatch desde la línea de comandos?

3.a) Añadir una imagen Docker en Cyberwatch

En la interfaz de Cyberwatch, cree una credencial registrada de tipo «Motor de ejecución Docker», introduciendo la URL con el formato «tcp://<IP_MOTEUR_DOCKER>:2376» y, a continuación, proporcione el certificado de la autoridad de certificación, así como el certificado del cliente y su clave privada.

A continuación, cree una segunda credencial de tipo «Registro Docker» e introduzca la URL del registro de GitLab junto con sus credenciales.

Después, puede crear un nuevo activo de tipo Imagen Docker introduciendo las credenciales anteriores y el nombre de la imagen que desea analizar (<group>/<project>/<image>:latest).

3.b) Utilizar la CLI de Cyberwatch para activar escaneos de imágenes Docker

La CLI de Cyberwatch le permite activar acciones desde la línea de comandos (CLI es el acrónimo de Command Line Interface). La CLI de Cyberwatch permite crear, actualizar y escanear imágenes Docker mediante llamadas sencillas desde la línea de comandos. La sintaxis de la CLI de Cyberwatch es la siguiente:

cyberwatch-cli [RECURSO] [ACCIÓN]

Para la gestión de imágenes Docker, utilizaremos:

  • RECURSO: docker-image
  • ACCIÓN: list, create, update o scan

La documentación completa de la CLI de Cyberwatch está disponible en GitHub.

La CLI de Cyberwatch puede integrarse en los comandos de las canalizaciones de GitLab para ejecutar análisis al vuelo.

Listar todas las imágenes de Docker con la CLI de Cyberwatch

El siguiente comando permite listar todas las imágenes de Docker presentes en su instancia de Cyberwatch:

cyberwatch-cli docker-image list

Analizar una imagen de Docker con la CLI de Cyberwatch

El enfoque recomendado para analizar una imagen de Docker con la CLI de Cyberwatch consiste en duplicar una imagen ya existente en la instancia de Cyberwatch y especificar únicamente los cambios necesarios, como por ejemplo, modificar las etiquetas (tags) que se van a analizar.

El siguiente comando permite, por ejemplo, analizar una imagen de Docker basándose en los parámetros de la imagen con ID 4 y cambiar su etiqueta a latest.

cyberwatch-cli docker-image create --from-image 4 --tag latest

También es posible introducir todos los parámetros manualmente para quienes deseen un control más preciso de todo el proceso. En ese caso, deberá especificar el nombre de la imagen, la etiqueta, su ID de registro, su ID de motor Docker y su ID de escáner.

El siguiente comando, por ejemplo, analizará la imagen Ubuntu con la etiqueta latest obtenida del registro con ID 7, ejecutando el análisis a través del motor Docker con ID 3 y activando el proceso desde el escáner de Cyberwatch con ID 1.

cyberwatch-cli docker-image create --name ubuntu --tag latest --registry-id 7 --engine-id 3 --node-id 1

Actualizar una imagen de Docker con la CLI de Cyberwatch

Para modificar una imagen de Docker, debe especificar su identificador junto con los parámetros que desea cambiar. La siguiente línea de comandos modifica la imagen de Docker analizada con ID 4, cambiando el nombre de la imagen y la etiqueta objetivo.

cyberwatch-cli docker-image update 4 --name ubuntu --tag latest

Relanzar el análisis de una imagen de Docker con la CLI de Cyberwatch

Para relanzar el análisis de una imagen, basta con especificar su ID de Cyberwatch.

cyberwatch-cli docker-image scan 4

El parámetro wait también permite esperar a que finalice el análisis antes de devolverle el control. Esto resulta muy útil para un enfoque de CI/CD.

cyberwatch-cli docker-image scan 4 --wait

Obtener las vulnerabilidades de una imagen con Cyberwatch CLI

Puede obtener la lista de vulnerabilidades asociadas a una imagen de Docker utilizando el siguiente comando (reemplace IMAGE_ID por el ID de la imagen correspondiente):

cyberwatch-cli docker-image show IMAGE_ID vulnerabilities

Por defecto, los resultados se obtienen en formato de texto. También puede solicitar a Cyberwatch que proporcione todos los resultados en formato Junit-XML para visualizar las CVE directamente en Gitlab.

cyberwatch-cli docker-image show IMAGE_ID vulnerabilities --format junit-xml

4) Escanear imágenes Docker automáticamente en un pipeline de Gitlab mediante Cyberwatch CLI

Ahora podemos combinar los elementos vistos anteriormente para activar escaneos de imágenes Docker mediante Cyberwatch CLI, directamente desde un pipeline de Gitlab.

Para ello, basta con crear una etapa en el pipeline de Gitlab que prefiera, con el fin de activar un escaneo de las imágenes siempre que sea necesario. A continuación, se muestra un extracto del archivo .gitlab-ci.yml:

docker-scan-image:
 stage: tests
 image:
   name: <gitlab_url>/<projet>/<nom_image>:latest
   entrypoint: [""]
 tags:
   - security-scans
 only:
   refs:
     - schedules
 script:
   - cyberwatch-cli docker-image scan $IMAGE_ID --wait
   - cyberwatch-cli docker-image show vulnerabilities $IMAGE_ID --format junit-xml | tee report.xml
 artifacts: *report_artifacts

Este fragmento, que puede adaptar a sus necesidades, permite activar un escaneo de vulnerabilidades en una imagen Docker desde un Scheduled Pipeline.

Los resultados de los escaneos aparecerán en Gitlab y, dependiendo de su configuración, pueden bloquear el pipeline si no desea que haya ninguna CVE.

Integre Cyberwatch en su cadena de integración y entrega continua y escanee las vulnerabilidades de sus imágenes Docker

Nuestra plataforma Cyberwatch le permite escanear vulnerabilidades y controlar el cumplimiento de sus activos de forma continua, incluso dentro de un pipeline de CI/CD.

Solicite una demostración a través de nuestro formulario y descubra todas las funcionalidades de nuestro software.

Gracias por enviar el formulario.