lefthookとtrivyでコミット前にローカルプロジェクトの脆弱性をチェックする
git commit
行う際に、クレデンシャル漏洩などを防止する目的でtrivyのスキャンを行いたくなったので、git hooksを利用してコミット前にコマンドを実行するようにしてみたいと思います。git hooksの管理ツールには Husky や pre-commit などのツールがありますが、今回はシングルバイナリで動作する lefthook を試してみました。
インストール
必要なコマンドをインストールします。手元の環境がMacなのでHomebrewを利用しています。
brew install trivy lefthook
手動でスキャンしてみる
まず手動でtrivyを実行して、認証情報が記載されたファイルを検出してくれるか試します。
$ cd repo
$ cat <<EOF > aws_credentials
[default]
aws_access_key_id=********************
aws_secret_access_key=****************************************
EOF
# スキャン実行
$ trivy fs . --quiet
aws_credentials (secrets)
Total: 2 (UNKNOWN: 0, LOW: 0, MEDIUM: 0, HIGH: 0, CRITICAL: 2)
CRITICAL: AWS (aws-access-key-id)
════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
AWS Access Key ID
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
aws_credentials:2
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
1 [default]
2 [ aws_access_key_id=********************
3 aws_secret_access_key=****************************************
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
CRITICAL: AWS (aws-secret-access-key)
════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
AWS Secret Access Key
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
aws_credentials:3
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
1 [default]
2 aws_access_key_id=********************
3 [ aws_secret_access_key=****************************************
4
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
想定通り警告してくれました。
lefthookのタスクを定義
検出してくれることを確認したので、lefthookを使って git commit
のタイミングでスキャンを実行するフックを作成していきます。
lefthook install
上記のコマンドを実行すると、リポジトリに lefthook.yml
ファイルが作成され、初期状態ではいくつかの設定例が記載されています。テンプレートと公式のドキュメントを参考に、次のように書き換えました。
pre-commit:
commands:
trivy-scan:
run: echo {staged_files} | xargs -n1 trivy fs --exit-code 1 --quiet
補足する点として、コミット対象のファイルのみにスキャンを行いたいので、{staged_files}
を指定しました。こうすることで、 pre-commit
のフック時にステージされているファイルのリストをスペース区切りで渡してくれます。
また、trivy fs
コマンドが受け取る引数は1つだけ(ディレクトリもしくは単一ファイルの指定)なので、xargs
でファイルの数だけ実行しています。加えて、デフォルトの挙動では脆弱性を検知した場合でも終了コードは0を返すため、--exit-code
フラグで検出時は1を返すように指定して、フックの中で実行された時にコミットが中断されるようにしました。(参考)
こちらもまずは手動で試してみます。lefthookはサブコマンドの run
で定義したフックを指定すると、タスクランナーのように利用することもできます。(タスク名には pre-commit
などのgit hooksに関連する名前以外も自由に利用可能です)
# ファイルをステージ
$ git add aws_credentials
# pre-commitフックを手動で実行
$ lefthook run pre-commit
Lefthook v1.2.8
SYNCING
SERVED HOOKS: pre-commit
RUNNING HOOK: pre-commit
EXECUTE > trivy-scan
/aws_credentials (secrets)
Total: 2 (UNKNOWN: 0, LOW: 0, MEDIUM: 0, HIGH: 0, CRITICAL: 2)
CRITICAL: AWS (aws-access-key-id)
════════════════════════════════════════
AWS Access Key ID
────────────────────────────────────────
/aws_credentials:2
────────────────────────────────────────
1 [default]
2 [ aws_access_key_id=********************
3 aws_secret_access_key=****************************************
────────────────────────────────────────
CRITICAL: AWS (aws-secret-access-key)
════════════════════════════════════════
AWS Secret Access Key
────────────────────────────────────────
/aws_credentials:3
────────────────────────────────────────
1 [default]
2 aws_access_key_id=********************
3 [ aws_secret_access_key=****************************************
4
────────────────────────────────────────
問題なさそうです。
git hooksからタスクが呼び出されるように設定
最後にgit hooksに登録して、定義した pre-commit
タスクがコミット時に実行されるかを確認します。
# git hooksに定義したタスクを登録
$ lefthook install
$ git commit -m "test"
Lefthook v1.2.8
RUNNING HOOK: pre-commit
EXECUTE > trivy-scan
/aws_credentials (secrets)
Total: 2 (UNKNOWN: 0, LOW: 0, MEDIUM: 0, HIGH: 0, CRITICAL: 2)
CRITICAL: AWS (aws-access-key-id)
════════════════════════════════════════
AWS Access Key ID
────────────────────────────────────────
/aws_credentials:2
────────────────────────────────────────
1 [default]
2 [ aws_access_key_id=********************
3 aws_secret_access_key=****************************************
────────────────────────────────────────
CRITICAL: AWS (aws-secret-access-key)
════════════════════════════════════════
AWS Secret Access Key
────────────────────────────────────────
/aws_credentials:3
────────────────────────────────────────
1 [default]
2 aws_access_key_id=********************
3 [ aws_secret_access_key=****************************************
4
────────────────────────────────────────
SUMMARY: (done in 0.66 seconds)
🥊 trivy-scan
これで git commit
の実行時にtrivyのスキャンが走り、脆弱性を検知した場合は中断されるようになりました。今回はクレデンシャルが含まれていないかをチェックするために使いましたが、DockerfileやKubernetesマニフェストの設定不備をチェックするなど様々な用途がありそうです。
該当のリポジトリを改めてcloneした時などは、再度 lefthook install
を実行する必要がありますので、READMEなどに書いておきましょう。なお、lefthookのインストールは npm
で行うこともできますが、その場合は postinstall スクリプトによって自動的に実行されるようです。
Discussion