This will walk through integrating Anchore scanning into a Gitlab container image build pipeline. During the first step, a Docker image will be built from a Dockerfile. Following this, during the second step Anchore will scan the image, and depending on the result of the policy evaluation, proceed to the final step. During the final step, the built image will be published and reports will be generated.

Follow along with this blog post by using the GitLab repo here.

This approach differs from previous posts where an Anchore engine service has been accessible from the build pipeline.

Prerequisites

  • Gitlab account
  • Dockerfile to build container image

Build Image

In the first stage of the pipeline, we build a Docker image from a Dockerfile as defined in our .gitlab-ci.yml

container_build:
stage: build
image: docker:stable
services:
- docker:stable-dind

variables:
DOCKER_DRIVER: overlay2

script:
- docker_login
- docker pull "${CI_REGISTRY_IMAGE}:${CI_COMMIT_REF_SLUG}" || true
- docker build --cache-from "${CI_REGISTRY_IMAGE}:${CI_COMMIT_REF_SLUG}" -t "$IMAGE_NAME" .
- docker push "$IMAGE_NAME"

Scan Image with Anchore

In the second stage of the pipeline, we scan the built image with Anchore as defined in our .gitlab-ci.yml:

container_scan:
stage: scan
image:
name: anchore/anchore-engine:latest
entrypoint: [""]
services:
- name: anchore/engine-db-preload:latest
alias: anchore-db

variables:
GIT_STRATEGY: none
ANCHORE_HOST_ID: "localhost"
ANCHORE_ENDPOINT_HOSTNAME: "localhost"
ANCHORE_CLI_USER: "admin"
ANCHORE_CLI_PASS: "foobar"
ANCHORE_CLI_SSL_VERIFY: "n"
ANCHORE_FAIL_ON_POLICY: "true"
ANCHORE_TIMEOUT: 500

script:
- |
curl -o /tmp/anchore_ci_tools.py https://raw.githubusercontent.com/anchore/ci-tools/master/scripts/anchore_ci_tools.py
chmod +x /tmp/anchore_ci_tools.py
ln -s /tmp/anchore_ci_tools.py /usr/local/bin/anchore_ci_tools
- anchore_ci_tools --setup
- anchore-cli registry add "$CI_REGISTRY" gitlab-ci-token "$CI_JOB_TOKEN" --skip-validate
- anchore_ci_tools --analyze --report --image "$IMAGE_NAME" --timeout "$ANCHORE_TIMEOUT"
- |
if ; then
anchore-cli evaluate check "$IMAGE_NAME"
else
set +o pipefail
anchore-cli evaluate check "$IMAGE_NAME" | tee /dev/null
fi

artifacts:
name: ${CI_JOB_NAME}-${CI_COMMIT_REF_NAME}
paths:
- image-*-report.json

Publish image

In the final stage of the pipeline, we push the Docker image to a registry as defined in the .gitlab.yml:

container_publish:
stage: publish
image: docker:stable
services:
- docker:stable-dind

variables:
DOCKER_DRIVER: overlay2
GIT_STRATEGY: none

script:
- docker_login
- docker pull "$IMAGE_NAME"
- docker tag "$IMAGE_NAME" "${CI_REGISTRY_IMAGE}:${CI_COMMIT_REF_SLUG}"
- docker push "${CI_REGISTRY_IMAGE}:${CI_COMMIT_REF_SLUG}"
- |
if ; then
docker tag "$IMAGE_NAME" "${CI_REGISTRY_IMAGE}:latest"
docker push "${CI_REGISTRY_IMAGE}:latest"
fi

Example

It contains a very simple Nodejs application, which is published to a registry as a runnable docker container.

After the container is built, it is sent through an Anchore engine scan.

  • anchore/anchore-engine:latest is used as the build container for the scan job.
  • anchore/engine-preload-db:latest is a postgres database, preloaded with the Anchore vulnerability data. This is used as a service in the scan job.
  • The default configuration for Anchore Engine is used on the build container.
  • Scans use the default Anchore policy. Using customized policies will become an option at a future time.
  • A timeout of 500s is used for this project, this value can be adjusted for whatever container is being scanned with the ANCHORE_TIMEOUT environment variable. Some containers take longer to scan than others.

To gate the container publish on a successful Anchore Engine scan, set the environment variable ANCHORE_FAIL_ON_POLICY='true'. This will cause the pipeline to fail if a scan fails.

Reports Provided by Anchore

When Anchore scanning finishes, by default, the following reports are available as artifacts. Report generation is configurable in anchore_ci_tools.py with the --content & --report flags.

  • image-content-os-report.json - all OS packages installed in the image
  • image-content-npm-report.json - all NPM modules installed in the image
  • image-content-gem-report.json - all Ruby gems installed in the image
  • image-content-python-report.json - all Python modules installed in the image
  • image-content-java-report.json - all Java modules installed in the image
  • image-vuln-report.json - all CVE's found in the image
  • image-details-report.json - image metadata utilized by Anchore Engine
  • image-policy-report.json - details of the policy applied to the Anchore scan