GitLab CIでTrivyを利用しDocker Imageの脆弱性を検知し、Slackに投稿する

tl;dr

  • Pipeline Schedule を利用し一定周期にscanを実行することで開発を止めずに脆弱性を検知する。
  • Slackに投稿することで脆弱性の検知をメンバーの目に入れることができる。

Trivyについて

昔書いたのでそちらを参照してください。 teitei-tk.hatenablog.com

コードを見せろ

Sample Repository

gitlab.com

Merge Request

gitlab.com

工夫したところ

gitlab-ci.ymlは特殊な事は書いておらず、ほとんどGitHubと、GitLabのサンプルコードをコピーしただけです。

工夫した点としては、Trivyの検知した結果のレポートをJUnitのフォーマットにしています。 GitHubのサンプルコードではGitLabのContainer scanningフォーマットで書かれていますが、Container ScanningはGold/Ultimate Planでないと利用できないため、JUnitフォーマットを利用しています。

今回はあえて、サンプルのため脆弱性のあるRack Gemなど、古いgemを利用しています。

JUnitフォーマットを利用した場合、MergeRequestの画面ではこのように表示されます。 f:id:teitei_tk:20201003212704p:plain

CVE-2019-16782などが表示されていることが確認できると思います。 リンクをクリックすると、CVEの詳細が表示されます。

f:id:teitei_tk:20201003213625p:plain

Schedule Pipelineを利用して一定周期でImageのScanを行う

新しくSchedule Pipelineを設定します。特に難しい点は無いと思うのでので設定は省略。 gitlab-ci.ymlの内容は下記です。特に変な点は書いていませんが、only: schedulesでSchedule Pipelineでのみ実行されるようにしています。

image_scan:
  image: docker:stable
  services:
    - name: docker:dind
  variables:
    DOCKER_HOST: tcp://docker:2375/
    DOCKER_DRIVER: overlay2
    # See https://github.com/docker-library/docker/pull/166
    DOCKER_TLS_CERTDIR: ""
    IMAGE: trivy-ci-test:$CI_COMMIT_SHA
  before_script:
    - export TRIVY_VERSION=$(wget -qO - "https://api.github.com/repos/aquasecurity/trivy/releases/latest" | grep '"tag_name":' | sed -E 's/.*"v([^"]+)".*/\1/')
    - echo $TRIVY_VERSION
    - wget --no-verbose https://github.com/aquasecurity/trivy/releases/download/v${TRIVY_VERSION}/trivy_${TRIVY_VERSION}_Linux-64bit.tar.gz -O - | tar -zxvf -
  script:
    # Build image
    - docker build -t $IMAGE .
    # Fail on high and critical vulnerabilities
    - ./trivy --exit-code 1 --cache-dir .trivycache/ --severity CRITICAL,HIGH,MEDIUM --no-progress $IMAGE
  cache:
    paths:
      - .trivycache/
  only:
    - schedules

設定すると、CI/CDページにてSchduleと表示されていることが確認できると思います。

f:id:teitei_tk:20201003213848p:plain

SlackへScan結果を通知する。

ここも特に難しいことはないです。SlackにてApps -> Incoming WebHooksを追加。WebHook URLをコピーし、GitLabRepositoryのSettings -> CI/CD -> Slack notificationに移動。

Pipelineにチェックを入れ、通知するSlack Channelを記入するだけ。

その後、Schedule Pipelineを実行すると、このようにSlackに通知されます。

f:id:teitei_tk:20201003214742p:plain