NOTE - Currently unstable and liable to change.
GitHub Action to statically analyze container images for vulnerabilities using Claircore.
name: Clairon:
push:
branches:
- 'main'pull_request:
branches:
- 'main'jobs:
docker-build:
name: "Docker Build"runs-on: ubuntu-lateststeps:
- name: Checkout codeuses: actions/checkout@v2
- name: Build an image from Dockerfilerun: | docker build -t a-really/great-app:${{ github.sha }} . - name: Save Docker imagerun: | docker save -o ${{ github.sha }} a-really/great-app:${{ github.sha }} - name: Run Clair V4uses: quay/clair-action@mainwith:
image-path: ${{ github.sha }}format: sarifoutput: clair_results.sarif
- name: Upload sarifuses: github/codeql-action/upload-sarif@v2with:
sarif_file: clair_results.sarifname: Clairon:
push:
branches:
- 'main'jobs:
docker:
runs-on: ubuntu-lateststeps:
-
name: Checkoutuses: actions/checkout@v2
-
name: Set up QEMUuses: docker/setup-qemu-action@v2
-
name: Set up Docker Buildxuses: docker/setup-buildx-action@v2
-
name: Login to DockerHubuses: docker/login-action@v2with:
username: ${{ secrets.DOCKERHUB_USERNAME }}password: ${{ secrets.DOCKERHUB_TOKEN }}
-
name: Build and pushuses: docker/build-push-action@v3with:
context: .push: truetags: user/app:latest
- name: Run Clair V4uses: quay/clair-action@mainwith:
image-ref: user/app:latestformat: sarifoutput: clair_results.sarif
- name: Upload sarifuses: github/codeql-action/upload-sarif@v2with:
sarif_file: clair_results.sarifThe 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
dockerbinary. 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: cion:
push:
branches:
- 'main'pull_request:
branches:
- 'main'jobs:
docker-pull-vulns:
name: "Docker Pull and get vulns"runs-on: ubuntu-lateststeps:
- name: Docker loginuses: docker/login-action@v2with:
registry: quay.iousername: ${{ secrets.QUAY_USERNAME }}password: ${{ secrets.QUAY_ROBOT_TOKEN }}
- name: Copy configrun: | cp ${HOME}/.docker/config.json config.json - name: Run Clair V4uses: quay/clair-action@mainwith:
image-ref: quay.io/crozzy/quay-test:v3.4.7-15format: sarifoutput: clair_results.sarifdocker-config-dir: /
- name: Upload sarifuses: github/codeql-action/upload-sarif@v2with:
sarif_file: clair_results.sarifAs 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.
name: db_updateon:
workflow_dispatch: {}# Run every day at 5AM UTCschedule:
- cron: '0 5 * * *'jobs:
docker:
runs-on: ubuntu-lateststeps:
- name: Set up QEMUuses: docker/setup-qemu-action@v1
- name: Set up Docker Buildxuses: docker/setup-buildx-action@v1
- name: Run Clair V4 updateuses: quay/clair-action@mainwith:
db-file: matcher.dbmode: update
- name: Cache DBuses: actions/cache@v3with:
path: matcher.dbkey: matcher.dbname: cion:
push:
branches:
- 'main'pull_request:
branches:
- 'main'jobs:
docker-build:
name: "Docker Build"runs-on: ubuntu-lateststeps:
- name: Checkout codeuses: actions/checkout@v2
- name: Grab cache DBuses: actions/cache@v3with:
path: matcher.dbkey: matcher.db
- name: Build an image from Dockerfilerun: | docker build -t crozzy/great-app:${{ github.sha }} . - name: Save Docker imagerun: | docker save -o ${{ github.sha }} crozzy/great-app:${{ github.sha }} - name: Run Clair V4uses: quay/clair-action@mainwith:
image-path: ${{ github.sha }}db-file: matcher.db # Use DB from cacheformat: sarifoutput: clair_results.sarif
- name: Upload artifactuses: actions/upload-artifact@v3with:
name: sarifpath: clair_results.sarif
- name: Upload sarifuses: github/codeql-action/upload-sarif@v2with:
sarif_file: clair_results.sarifFollowing 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). The image must follow the OCI Image Spec https://github.com/opencontainers/image-spec/blob/v1.1.1/image-layout.md (this means using the --format oci-archive flag for podman save). |
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.
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