November 19, 2017

Container vulnerability scan using CoreOS Clair

Docker Enterprise EE and it’s trusted registry has this great feature for security scanning images, which can be included in promotion policies and so on.

If you however are not using EE or either DTR, there’s an awesome project from the CoreOS team called Clair. Just check the intergrations for a list of projects using it.

I’ve started using this in Gitlab CI as an additional step to check images before uploading it to the builtin registry.

Basically, you’ll need to have a Clair server running (plus database) and then instruct the API to scan an image from a registry. As we want to do this BEFORE pushing it to the registry, there’s another awesome tool called clair-scanner which spins up a local endpoint for Clair to check the image layers.

Armin Coralic also provides some pre-built images for Clair which makes it really easy to use. In my case, i just spin up an instance in my Docker Swarm using this compose yaml (you can adjust the database tag, he’s building regularly):

version: '3.1'
services:

  postgres:
    image: arminc/clair-db:2017-10-29
    networks:
      - clair-backend

  clair:
    image: arminc/clair-local-scan:v2.0.1
    networks:
      - clair-backend
    ports:
      - 6060:6060
      - 6061:6061

networks:
  clair-backend:
    driver: overlay

Now, i can put something like this in my Gitlab CI file:

## snip ##
  script:
    - docker build -t ${CI_PROJECT_NAME,,}:${CI_COMMIT_REF_NAME} .
    - curl -sL https://github.com/arminc/clair-scanner/releases/download/v6/clair-scanner_linux_amd64 -o clair-scanner
    - chmod +x clair-scanner
    - ./clair-scanner --clair=${CLAIR} --ip $(hostname -i) ${CI_PROJECT_NAME}:${CI_COMMIT_REF_NAME}
    - echo ${CI_BUILD_TOKEN} | docker login -u gitlab-ci-token --password-stdin ${CI_REGISTRY}
    - docker tag ${CI_PROJECT_NAME,,}:${CI_COMMIT_REF_NAME} ${CI_REGISTRY}/${CI_PROJECT_NAMESPACE,,}/${CI_PROJECT_NAME,,}:${CI_COMMIT_REF_NAME}
    - docker push ${CI_REGISTRY}/${CI_PROJECT_NAMESPACE,,}/${CI_PROJECT_NAME,,}:${CI_COMMIT_REF_NAME}
    - docker rmi ${CI_PROJECT_NAME,,}:${CI_COMMIT_REF_NAME}
## snip ##

If the scan fails, the image won’t be pushed to the registry, yeah.