/clair-action

Clair in the CI. Github actions, tekton pipelines etc.

Primary LanguageGo

About

NOTE - Currently unstable and liable to change.

GitHub Action to statically analyze container images for vulnerabilities using Claircore.


Usage

Image path

name: Clair

on:
  push:
    branches:
      - 'main'
  pull_request:
    branches:
      - 'main'
jobs:
  docker-build:
    name: "Docker Build"
    runs-on: ubuntu-latest
    steps:

      - name: Checkout code
        uses: actions/checkout@v2

      - name: Build an image from Dockerfile
        run: |
          docker build -t a-really/great-app:${{ github.sha }} .

      - name: Save Docker image
        run: |
          docker save -o ${{ github.sha }} a-really/great-app:${{ github.sha }}

      - name: Run Clair V4
        uses: quay/clair-action@main
        with:
          image-path: ${{ github.sha }}
          format: sarif
          output: clair_results.sarif
  
      - name: Upload sarif
        uses: github/codeql-action/upload-sarif@v2
        with:
          sarif_file: clair_results.sarif

Image ref

name: Clair
on:
  push:
    branches:
      - 'main'
jobs:
  docker:
    runs-on: ubuntu-latest
    steps:
      -
        name: Checkout
        uses: actions/checkout@v2
      -
        name: Set up QEMU
        uses: docker/setup-qemu-action@v2
      -
        name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v2
      -
        name: Login to DockerHub
        uses: docker/login-action@v2
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}
      -
        name: Build and push
        uses: docker/build-push-action@v3
        with:
          context: .
          push: true
          tags: user/app:latest
      - 
        name: Run Clair V4
        uses: quay/clair-action@main
        with:
          image-ref: user/app:latest
          format: sarif
          output: clair_results.sarif
  
      - name: Upload sarif
        uses: github/codeql-action/upload-sarif@v2
        with:
          sarif_file: clair_results.sarif

Image ref with auth

The decision was taken (that might be changeable) to just ask for the .docker/config.json file (or whereever you keep your container registry authentication configuration). The reasons for this are:

  • Most people in their workflows are going to have logged into docker, or can do it easily with the docker-login action. This action already accounts for the various registry special cases.
  • The clair-action container does no need to depend on the docker binary. Here is an example of how to define a workflow to use the clair-action on a private image that exists in a registry:
name: ci

on:
  push:
    branches:
      - 'main'
  pull_request:
    branches:
      - 'main'
jobs:
  docker-pull-vulns:
    name: "Docker Pull and get vulns"
    runs-on: ubuntu-latest
    steps:
      - name: Docker login
        uses: docker/login-action@v2
        with:
          registry: quay.io
          username: ${{ secrets.QUAY_USERNAME }}
          password: ${{ secrets.QUAY_ROBOT_TOKEN }}
      - name: Copy config
        run: |
          cp ${HOME}/.docker/config.json config.json
      - name: Run Clair V4
        uses: quay/clair-action@main
        with:
          image-ref: quay.io/crozzy/quay-test:v3.4.7-15
          format: sarif
          output: clair_results.sarif
          docker-config-dir: /
      - name: Upload sarif
        uses: github/codeql-action/upload-sarif@v2
        with:
          sarif_file: clair_results.sarif

Generating vulnerability DB and using it for report creation

As the vulnerability database isn't hosted anywhere, it is the responsibility of the user to generate it. Clair-action surfaces an update mode to allow users to do this.

Generate the vulnerability DB example:

name: db_update

on:
  workflow_dispatch: {}
  # Run every day at 5AM UTC
  schedule:
    - cron: '0 5 * * *'

jobs:
  docker:
    runs-on: ubuntu-latest
    steps:
      - name: Set up QEMU
        uses: docker/setup-qemu-action@v1

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v1

      - name: Run Clair V4 update
        uses: quay/clair-action@main
        with:
          db-file: matcher.db
          mode: update

      - name: Cache DB
        uses: actions/cache@v3
        with:
          path: matcher.db
          key: matcher.db

Using generated database:

name: ci

on:
  push:
    branches:
      - 'main'
  pull_request:
    branches:
      - 'main'
jobs:
  docker-build:
    name: "Docker Build"
    runs-on: ubuntu-latest
    steps:

      - name: Checkout code
        uses: actions/checkout@v2

      - name: Grab cache DB
        uses: actions/cache@v3
        with:
          path: matcher.db
          key: matcher.db

      - name: Build an image from Dockerfile
        run: |
          docker build -t crozzy/great-app:${{ github.sha }} .
      - name: Save Docker image
        run: |
          docker save -o ${{ github.sha }} crozzy/great-app:${{ github.sha }}
      - name: Run Clair V4
        uses: quay/clair-action@main
        with:
          image-path: ${{ github.sha }}
          db-file: matcher.db  # Use DB from cache
          format: sarif
          output: clair_results.sarif
      - name: Upload artifact
        uses: actions/upload-artifact@v3
        with:
          name: sarif
          path: clair_results.sarif
      - name: Upload sarif
        uses: github/codeql-action/upload-sarif@v2
        with:
          sarif_file: clair_results.sarif

Customizing

inputs

Following inputs can be used as step.with keys

Name Type Required default Description
image-ref String yes* - The reference to an image in a container registry, currently this needs to be public (e.g., quay.io/projectquay/clair:nightly)
image-path String yes* - Where on the filesystem the image was saved, i.e. the --output-flag from the docker save command the action require either this or image-ref to be defined (e.g., /tmp/my-image.tar)
format String no clair The output format of the report, currently clair, sarif and quay are supported.
output String yes - The file path where the report gets saved (e.g., /tmp/my-image-report.sarif)
return-code String no 0 A code to return from the process if Clair found vulnerabilities. (e.g., 1)
mode String no report Specify which mode to run the action in, supported values are report and update. report reports vulnerabilities for an image, update update generates the sqlite3 vulnerability DB.
db-file String no empty string Optional param to specify where on the filesystem the zstd compressed sqlite3 DB lives.
db-file-url String no liable to change Optional param to specify your own url where the zstd compressed sqlite3 DB lives.
docker-config-dir String no - Optional param to specify the docker (or other) config dir to allow for pulling of layers from private images

* either image-ref or image-path need to be defined.

Releases

Before tagging make sure to update the Dockerfile, this must happen for the action to use the correct container. The container is pre-built to keep latency as low as possible, pushing a tag should trigger that container build that is subsequently pushed to Quay.io.

# Update Dockerfile with new $TAG
git tag -as $TAG HEAD
git push upstream $TAG
gh workflow view release --web # if you're partial to that kind of thing