🍣

pre-commit: gitコミット前に認証情報など不正なコードが紛れ込んでないかチェックするツール

2024/01/28に公開

pre-commitはgitコミットを行う前に以下のようなチェックを行なって、もし違反するコードを発見した場合にgitコミットをキャンセルするツールである。

  • JSON, YAML, TOMLなどの設定ファイルの文法をチェック
  • 行末尾やファイル末尾に余計な空白や改行が含まれていないかチェック
  • ソースコードやドキュメント等に対してフォーマッタの適用
  • 誤ってaws_access_key_idやGCPのクレデンシャルJSONといったセンシティブな情報が平文で含まれていないかのチェック
  • アプリケーションで使用しているライブラリ、パッケージの脆弱性診断
  • その他、任意のバリデーションスクリプトの実行 ...etc

以上のように大抵のチェックが可能であるため、インフラプロジェクト、アプリケーションプロジェクト問わず常に導入をおすすめしたいツールである。

他にもテストコードの実行等も行うことはできるが、git commitの度にテストが完了するまで数分〜数十分以上待たされるのはストレスが溜まるので、基本的に時間がかかるチェックはCIに任せるなどある程度の分業を考える必要がある。

インストール

Macのhomebrewを使用している場合、pre-commitは以下のコマンドでインストールできる。

$ brew install pre-commit

pipによるインストール方法はこちら

pre-commitではコミットを実行する前に行うチェックを.pre-commit-config.yamlという名前の設定ファイルに定義して、プロジェクトルートに配置する必要がある。

(自分のインフラプロジェクトにおける.pre-commit-config.yamlの設定例はこちら)

1. OSSのhookを使用

だいたいのチェックはOSSで公開されているhookを利用するだけで実施したいチェックを実現できる。

  • JSON, YAML, TOMLなどの設定ファイルの文法のチェック
  • 行末尾やファイル末尾に余計な空白や改行が含まれていないかチェック

のチェックはpre-commit-hooksを使用して、以下のような設定を記述する。

.pre-commit-config.yaml
$ cd /path/to/your-project
$ vi .pre-commit-config.yaml
# trueに設定した場合、1つでもチェックに引っかかった時点でエラー終了
fail_fast: true

repos:
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v4.5.0
    hooks:
      - id: check-json
      - id: check-toml
      - id: check-yaml
      - id: trailing-whitespace

設定を記述したら、コミット時にチェックが行われるよう以下のインストールコマンドを実行する。

$ pre-commit install

これでコミットを実行した際に変更ファイルにJSON、YAML、TOMLなどが含まれていればhookが実行されるようになる。

そして変更の中にもしフォーマットの不正が含まれていた場合、以下のようにエラーでコミットがキャンセルされるようになる。

エラーの原因を修正したら、再度git addコマンドを実行してコミットを行うことで再びチェックが実行される。

なお使用可能なhookの一覧は公式ドキュメントで公開されている。

ここでは有名なものから草OSSまで無差別に列挙されているので、セキュリティの観点から使用したいと思うhookでも本当に導入して良いか確かめてから利用するようにしたい。

2. 任意のスクリプトをhookとして実行

  • 誤ってaws_access_key_idやGCPのクレデンシャルJSONなどのセンシティブな情報が平文で含まれていないかのチェック
  • アプリケーションで使用しているライブラリ、パッケージの脆弱性診断

はセキュリティツールTrivyで実行可能だが、以下のように.pre-commit-config.yamlを設定することで、任意のコマンドやスクリプトをhookとして実行することも出来る。

(Trivyの詳細についてはこちら)

# セキュリティチェックを実行するシェルスクリプトを作成
$ vi trivy.sh
#!/bin/bash

set -eu

trivy fs --scanners vuln,secret,misconfig,license --exit-code=1 ./

# pre-commitでチェックシェルを実行するよう設定
$ vi .pre-commit-config.yaml
fail_fast: true

repos:
  - repo: local
    hooks:
      - id: trivy
        name: run trivy
        entry: ./trivy.sh
        language: system

repo: localentryにコマンドを定義することで、自作のチェックが可能になる。

上記設定では、どんなファイルが変更されてもTrivyのセキュリティスキャンが行われるようになっているが、files属性やexclude、exclude_types属性を設定することで、特定のファイルを変更した場合にのみhookが実行されるように設定することも出来る。

(設定可能な項目は公式ドキュメントを参照)

なおtrivyによるセキュリティスキャン実行時に脆弱性スキャン等も同時に行おうとすると脆弱性DBの更新などに時間がかかることがあるため、シークレット情報のチェックのみを行いたい場合は、--scannersオプションの値をsecretのみに限定した方が良い。

あとMarkDown(.md)ファイル等はデフォルトでsecretのスキャン対象とならないため、個人的にはtrivy-secret.yamlを作成して以下のような設定をすることをおすすめする。

(secretスキャンの対象とならない条件についてはこちらを参照)

trivy-secret.yaml
disable-allow-rules:
  - markdown
  - tests
  - examples

Discussion