継続は力なり

タイトル通り定期的な更新を心掛けるブログです。

CI に Trivy を組み込んで脆弱性スキャンを行った結果を Slack に通知する

タダです.

業務の中で CodeBuild にてコンテナビルド後,Trivy によるコンテナイメージの脆弱性スキャンをして Slack に通知する仕組みを作る検証を行ったので,検証した内容をこの記事にまとめていきます.

Trivy について

コンテナ脆弱性スキャンツールとして有名で自分も知っていたものの使う機会がなかった中,脆弱性をチェックしていくことを定期的にやっていくべきだと言う理由から Trivy を使っていくことにしました.開発者は Teppei Fukuda さんで,このブログも見たことある方多いのではないでしょうか?

github.com

Trivy の特徴はドキュメントにもあるように脆弱性データベースから OS や言語別のパッケージの脆弱性を検出することができます.また,単一のバイナリをインストールするだけで使えるため,導入のハードルも低いなと感じます.

Trivy detects vulnerabilities of OS packages (Alpine, RHEL, CentOS, etc.) and language-specific packages (Bundler, Composer, npm, yarn, etc.)

Just install the binary and you're ready to scan.

CodeBuild への Trivy 組み込み

CodeBuild への Trivy を組み込むのに際しては,AWS の『How to build a CI/CD pipeline for container vulnerability scanning with Trivy and AWS Security Hub』を参考に進めました.ブログでは Security Hub に診断結果を入れて管理していましたが,相談した結果脆弱性スキャンの結果はHIGHCRITICALが出たら Slack に通知するのを仕込むことにしました(管理は別の場所で行う).

CodeBuild の buildspec.yml の定義

CodeBuild のbuildspec.ymlこちらを参考に進めました.検証では下記のような定義を作りました.

phases:
  install:
    commands:
      - "apt update"
      - "apt install rpm -y"
      - "wget https://github.com/aquasecurity/trivy/releases/download/v0.19.2/trivy_0.19.2_Linux-64bit.deb"
      - "dpkg -i trivy_0.19.2_Linux-64bit.deb"
~中略~
  build:
    commands:
      ~中略~
      - trivy -f json -o results.json --exit-code 0 --severity HIGH,CRITICAL [コンテナイメージ名]
~中略~
  post_build:
    commands:
      ~中略~
      - echo trivy scan results S3 upload on `date`
      - aws s3 cp results.json s3://[アップロードするバケット名]
~中略~

Slack 通知のためにやったこと

Trivy ではスキャンの結果を JSON 出力できるため,JSON ファイルを S3 にアップロードしてバケットにデータを保管し,S3 へのPUT をトリガーに Lambda を発火するようにしました.

f:id:sadayoshi_tada:20210921174348p:plain f:id:sadayoshi_tada:20210921174423p:plain

Lambda が Slack に投稿する内容は以下の項目を抽出して投稿しています.

  • CVE番号
  • ライブラリ名
  • 対象バージョン
  • 緊急度
  • 脆弱性のURL

投稿のイメージ f:id:sadayoshi_tada:20210921223327p:plain

コードはこちらのコードを参考に書いています.サンプルコードの中では JSON の要素的に1つ目で Vulnerabilities があるときはいいのですが,ない時もあるため JSON の要素数分繰り返して Vulnerabilities があるかどうかを判定するようにしました.

response = s3.get_object(Bucket=bucket, Key=key)
body = response['Body'].read()
scan_data = json.loads(body)
json_lens = len(scan_data)
for i in range(json_lens):
     if 'Vulnerabilities' in scan_data[i]:
         for p in scan_data[i]['Vulnerabilities']:
               cveId = str(p['VulnerabilityID'])
               packageName = str(p['PkgName'])
               installedVersion = str(p['InstalledVersion'])
               aquaUrl = str(p['PrimaryURL'])
               trivySeverity = str(p['Severity'])

まとめ

CodeBuild の CI で Trivy を導入,脆弱性スキャンを行ってみたのとその結果を Slack に通知する仕組みを検証したのでその模様をまとめました.今回は CodeBuild の中に入れましたが,GitHub Actions も用意されているためこちらも使ってみたいと思います.

github.com