How do I scan Docker image vulnerabilities in a GitLab pipeline using Cyberwatch?

Cyberwatch allows you to scan Docker images for vulnerabilities. This process can be very useful when used in a CI/CD process, particularly in a GitLab pipeline, especially as part of a DevSecOps approach.

In this article, we will look at:

  1. How to create a Docker image from a GitLab pipeline;
  2. How to scan these images in Cyberwatch.

Introduction: Why scan Docker image vulnerabilities in a DevSecOps GitLab pipeline?

What is a CI/CD process?

IT development teams frequently use forge software to collaborate. A forge provides a more user-friendly collaborative layer on top of version control systems like Git or Mercurial. The most common forge software offers features for bug tracking, continuous integration, and continuous delivery.

These last two terms, continuous integration and continuous delivery, are more commonly referred to by their acronym, CI/CD.

A CI/CD process is a system of continuous integration and continuous delivery, meaning a setup where every new line of code from a developer is pushed to a shared repository, then triggers non-regression and functional validation tests (the CI part), as well as automated deployment steps across various environments (the CD part).

A CI/CD process is implemented as a series of linked steps, creating what is known as a pipeline.

CI/CD processes are widely used in "DevOps" practices, where deployment steps are automated using code.

In this article, we focus on GitLab pipelines, a widely used open-source forge software, particularly valued for its ability to be deployed in "self-hosted" mode.

Why scan Docker images for vulnerabilities?

A CI/CD process can produce deliverables known as software artifacts. A classic example is the production of Docker images, built by the CI/CD pipeline.

Automated Docker image production allows, for example, having a Docker image for every new change made to the software developed by a team, making it easier to deploy and test these changes in dedicated environments.

However, a Docker image contains components that are subject to vulnerabilities, at the very least those identified in CVE databases.

These potentially vulnerable components include, for example, packages linked to the image's base system (such as DPKG packages installed on a Debian Docker image), binaries deployed within the image, or software libraries used by various programming languages (PIP, GEM, NPM, PHAR modules, etc.).

Every Docker image should therefore be scanned regularly for vulnerabilities to determine the risks involved and make informed decisions accordingly.

When security steps are added to a DevOps approach, it is referred to as "DevSecOps," indicating that IT security verification steps are also automatically checked with every change to an IT project.

Why scan a Docker image in a CI/CD process?

The primary goal of a CI/CD process is to improve the quality of developed software by regularly running functional and security tests.

A well-known step in CI/CD is Static Application Security Testing (SAST), which identifies potential errors introduced into the code that could lead to SQL or XSS injections.

Another increasingly common step in a CI/CD process is the vulnerability scan, where the Docker images produced during the process are scanned to determine whether to authorize or block their deployment to production.

This allows for the early identification of CVE vulnerabilities in deployed components, enabling them to be fixed before they can impact client environments.

1) How to scan a Docker image with Cyberwatch from a GitLab pipeline?

1.a) Prerequisites

To connect Cyberwatch to a GitLab pipeline and scan the associated Docker images, you will need the following:

  • A Docker runtime engine (i.e., a machine with Docker Engine installed);
  • Docker images to be retrieved from a GitLab pipeline.

The GitLab pipeline will control Cyberwatch via API to specify an image to scan. Cyberwatch will analyze this image using the Docker runtime engine and send the results back to the GitLab pipeline in Junit-XML format.

1.b) Configuring the Docker runtime engine to make it accessible to Cyberwatch

First, we will configure Docker to authorize connections and commands sent by Cyberwatch.

To ensure these operations occur via secure communication, you will need the following:

  • A certificate authority, along with its certificate;
  • A client certificate signed by the certificate authority;
  • A private key associated with the client certificate.

Generate the certificate authority certificate

To generate a certificate authority and its certificate, we will run the following command lines.

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

Generate the client certificate and private key

To generate the private key, we will enter the following command lines:

openssl genrsa -out dockerdkey.pem 4096

Next, to generate the client certificate, we will use the lines below, replacing <IP> with the IP address of the Docker machine:

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')

Configure the DockerD service to use the generated certificates

Once the certificates are generated, we need to configure DockerD to use the newly created certificates. To do this, we will modify the /etc/docker/daemon.json file by adding the following elements:

{
   "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"
}

You must then restart Docker for the configuration to take effect, using the commands below:

systemctl daemon-reload
systemctl restart docker

2) How do I build a Docker image in a GitLab pipeline?

We will use the GitLab Container Registry, which has been included by default in GitLab since version 8.8, to store our images.

The GitLab Container Registry allows you to test, build, and deploy your projects using a Docker image created directly within GitLab.

For this demonstration, we can use a very simple Dockerfile based on Nginx:

FROM nginx:alpine

To push this image to the GitLab registry via the pipeline, we use the .gitlab-ci.yml file below (replacing <group>, <project>, and <image> with the appropriate parameters for your GitLab project):

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

This configuration allows you to log in to the GitLab Container Registry, build a Docker image from the previous Dockerfile, and push it to the registry.

3) How do I scan a Docker image using the Cyberwatch command line?

3.a) Adding a Docker image to Cyberwatch

In the Cyberwatch interface, create a saved credential of the "Docker Runtime" type, entering the URL in the format "tcp://<IP_MOTEUR_DOCKER>:2376", then provide the certificate authority certificate, as well as the client certificate and its private key.

Next, create a second credential of the "Docker Registry" type and enter the GitLab registry URL along with your credentials.

You can then create a new Docker Image asset by entering the previous credentials and the name of the image you wish to analyze (<group>/<project>/<image>:latest).

3.b) Using the Cyberwatch CLI to trigger Docker image scans

The Cyberwatch CLI allows you to trigger actions via the command line (CLI stands for Command Line Interface). The Cyberwatch CLI makes it possible to create, update, and scan Docker images using simple command-line calls. The syntax for the Cyberwatch CLI is as follows:

cyberwatch-cli [RESOURCE] [ACTION]

For managing Docker images, we will use:

  • RESOURCE: docker-image
  • ACTION: list, create, update, or scan

The full Cyberwatch CLI documentation is available at GitHub.

The Cyberwatch CLI can be integrated into GitLab pipeline commands to trigger scans on the fly.

Listing all Docker images with the Cyberwatch CLI

The following command lists all Docker images present on your Cyberwatch instance:

cyberwatch-cli docker-image list

Scanning a Docker image with the Cyberwatch CLI

The recommended approach for scanning a Docker image with the Cyberwatch CLI is to duplicate an existing Docker image already present on the Cyberwatch instance and specify only the necessary changes, such as updating the tags to be scanned.

For example, the command below scans a Docker image based on the parameters of the image with ID 4, while updating its tag to latest.

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

It is also possible to provide all parameters manually for those who require finer control over the entire process. In this case, you must specify the image name, tag, registry ID, Docker engine ID, and scanner ID.

For example, the command below scans the Ubuntu image with the latest tag from the registry with ID 7, initiates the scan via the Docker engine with ID 3, and triggers the process from the Cyberwatch scanner with ID 1.

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

Updating a Docker image with the Cyberwatch CLI

To modify a Docker image, you must specify its identifier along with the parameters to be updated. The command line below modifies the scanned Docker image with ID 4 by changing the targeted image name and tag.

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

Rerunning a Docker image scan with the Cyberwatch CLI

To rerun a scan for an image, simply specify its Cyberwatch ID.

cyberwatch-cli docker-image scan 4

The wait parameter also allows you to wait for the scan to complete before returning control. This is highly useful for CI/CD workflows.

cyberwatch-cli docker-image scan 4 --wait

Retrieve image vulnerabilities with Cyberwatch CLI

You can retrieve the list of vulnerabilities associated with a Docker image using the following command (replace IMAGE_ID with the ID of the target image):

cyberwatch-cli docker-image show IMAGE_ID vulnerabilities

By default, results are provided in text format. You can also request that Cyberwatch provide all results in Junit-XML format to display CVEs directly in Gitlab.

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

4) Automatically scan Docker images in a Gitlab pipeline using the Cyberwatch CLI

We can now assemble the elements covered previously to trigger Docker image scans using the Cyberwatch CLI, directly from a Gitlab pipeline.

To do this, simply create a stage in the Gitlab pipeline of your choice to trigger an image scan whenever necessary. A snippet of a .gitlab-ci.yml file is provided below:

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

This snippet, which can be adapted to your needs, allows you to trigger a vulnerability scan on a Docker image from a Scheduled Pipeline.

The scan results will then appear in GitLab and can trigger a pipeline failure if you wish to block any CVEs, depending on your settings.

Integrate Cyberwatch into your CI/CD pipeline and scan your Docker images for vulnerabilities

Our vulnerability management software allows you to manage vulnerabilities and continuously monitor the compliance of your assets, including within a CI/CD pipeline.

Request a demo via our form and discover all the features of our software.

Thanks for submitting the form.