Docker Security Scanning (DSS) with CoreOS’s — Clair

D. Heinrich
3 min readSep 24, 2019

Recently we descovered a CVE within one of our development images. Therfore we wanted to not happen this again. So we got going with docker security scanning. Quick we found Clair by CoreOS wich seams to be reasonable for our purposes.

Clair is an open source project for the static analysis of vulnerabilities in application containers (currently including appc and docker).

In regular intervals, Clair ingests vulnerability metadata from a configured set of sources and stores it in the database.

Clients use the Clair API to index their container images; this creates a list of features present in the image and stores them in the database.

Clients use the Clair API to query the database for vulnerabilities of a particular image; correlating vulnerabilities and features is done for each request, avoiding the need to rescan images.

When updates to vulnerability metadata occur, a notification can be sent to alert systems that a change has occurred.

So what do you need to get started with CoreOS — Clair?

  • docker
  • docker-compose
  • clair config
  • Postgres

For ease we are putting it all together in a docker-compose.yml.

All our files will be placed under docker-clair and all written files by the containers are placed in docker-clair/data/... .

Building

First off, creating the directory structure:

mkdir -p docker-clair/data/clair/config

$ cat <<EOF > docker-clair/docker-compose.yml
version: "3.0"
services:
# POSTGRES
postgres:
container_name: clair_postgres
image: postgres:latest
user: "${UID}:${GID}"
restart: unless-stopped
environment:
POSTGRES_PASSWORD: changemeplease
volumes:
- ./data/postgres:/var/lib/postgresql/data
networks:
- clair
# CLAIR
clair:
container_name: clair_clair
image: quay.io/coreos/clair:latest
user: "${UID}:${GID}"
restart: unless-stopped
depends_on:
- postgres
volumes:
- ./data/clair/tmp:/tmp
- ./data/clair/config:/config
ports:
- 6060:6060
- 6061:6061
networks:
- clair
command: [--log-level=debug, --config, /config/config.yml]
networks:
clair:
driver: bridge
EOF

Clair’s config.yml

You can either use mine or just fetch the original one here: config.yaml.sample

$ cat <<EOF > docker-clair/data/clair/config/config.yml
clair:
database:
type: pgsql
options:
source: host=postgres port=5432 user=postgres password=changemeplease sslmode=disable statement_timeout=60000
cachesize: 16384
api:
port: 6060
healthport: 6061
timeout: 900s
updater:
interval: 2h
notifier:
attempts: 3
renotifyinterval: 2h
EOF

NOTE:

  1. Please edit the PGSQL Password from changemeplease to anything you prefer as a password!
  2. Do not quote the PGSQL password in config.yml it will not work.

Running

To start the docker-clair you can simple run the following:

$ cd docker-clair
$ docker-compose up -d && docker-compose logs -f

Now you can see by typing docker-compose ps that you have clair up and running under port 6060.

$ docker-compose ps
WARNING: The UID variable is not set. Defaulting to a blank string.
WARNING: The GID variable is not set. Defaulting to a blank string.
Name Command State Ports
--------------------------------------------------------------------------------------------------------
clair_clair /clair --log-level=debug - ... Up 0.0.0.0:6060->6060/tcp, 0.0.0.0:6061->6061/tcp
clair_postgres docker-entrypoint.sh postgres Up 5432/tcp

Scanning

There are several tools to actually use clair available here.

I personally use klar at the moment so I will put how I use it currently.

You can get it by using: go get github.com/optiopay/klar . Verify installation by using

$ which klar
[...]/.go/bin//klar

We need some ENVs specified first, depending on your registry.
See the README.md on Github to find the fits most for your needs.

I use the following:

# this works for Dockerhub:
export DOCKER_INSECURE=true
export REGISTRY_INSECURE=false
export CLAIR_ADDR=clair.example.org:6060
# Own registry with basic-auth
export DOCKER_USER=<Registry Username>
export DOCKER_PASSWORD=<Registry Password>

If the ENVs are set-up you can use klar with clair by simple typing klar followed by the image, in my case I fetch the python:3.5 image directly from DockerHub.

$ klar python:3.5
clair timeout 1m0s
docker timeout: 1m0s
no whitelist file
Analysing 9 layers
Got results from Clair API v1
Found 0 vulnerabilities

Conclusion

Basic security scanning with docker is not to hard at all.

There are several other tools like docker-bench-security etc. in place.

See the article by Sysdig here to may find a better solution for your needs.

Thats all I have/know about this topic so far, if you have any further questions or comments, please use the section below.

Thanks for reading,

Cheers!

--

--

D. Heinrich

Working as a Head of Infrastructure at Flower Labs.