GitHub で awslabs のリポジトリを眺めてたら git-secrets という便利なツール(シェルで実装されてる)を発見した.
どんなものかを簡単に説明すると,アクセスキーなどを誤ってコミットすることを Git の hooks を使って未然に防ぐツールで,誤って GitHub に push してしまったために,AWS を不正利用されてしまった,みたいな事故もたまに聞くし,そういうのを防ぐことができる.非常に良かったので,一部のリポジトリに git-secrets を設定した.
インストール
make install
でも良いけど,Mac なら brew が使える.
$ brew install git-secrets
インストールすると git secrets
コマンドが使えるようになった.
$ git secrets usage: git secrets --scan [-r|--recursive] [--cached] [--no-index] [--untracked] [<files>...] or: git secrets --scan-history or: git secrets --install [-f|--force] [<target-directory>] or: git secrets --list [--global] or: git secrets --add [-a|--allowed] [-l|--literal] [--global] <pattern> or: git secrets --add-provider [--global] <command> [arguments...] or: git secrets --register-aws [--global] or: git secrets --aws-provider [<credentials-file>] --scan Scans <files> for prohibited patterns --scan-history Scans repo for prohibited patterns --install Installs git hooks for Git repository or Git template directory --list Lists secret patterns --add Adds a prohibited or allowed pattern, ensuring to de-dupe with existing patterns --add-provider Adds a secret provider that when called outputs secret patterns on new lines --aws-provider Secret provider that outputs credentials found in an ini file --register-aws Adds common AWS patterns to the git config and scans for ~/.aws/credentials -r, --recursive --scan scans directories recursively --cached --scan scans searches blobs registered in the index file --no-index --scan searches files in the current directory that is not managed by Git --untracked In addition to searching in the tracked files in the working tree, --scan also in untracked files -f, --force --install overwrites hooks if the hook already exists -l, --literal --add and --add-allowed patterns are escaped so that they are literal -a, --allowed --add adds an allowed pattern instead of a prohibited pattern --global Uses the --global git config
ちなみに,コマンド自体は /usr/local/bin/git-secrets
にある.
$ which git-secrets
/usr/local/bin/git-secrets
セットアップ
git-secrets のセットアップはリポジトリ単位に行う.適当なリポジトリのルートディレクトリに移動して git secrets --install
を実行すると,3種類の hooks が登録される.
$ git secrets --install
✓ Installed commit-msg hook to .git/hooks/commit-msg
✓ Installed pre-commit hook to .git/hooks/pre-commit
✓ Installed prepare-commit-msg hook to .git/hooks/prepare-commit-msg
ただし,既に hooks を使っている場合,エラーになる.この場合は --force
オプションを付けて強制的に上書きする必要がある.
$ git secrets --install .git/hooks/commit-msg already exists. Use -f to force
残念ながらマージする機能はないため,一度 hooks を退避した後に上書きして,戻す必要がありそう.
$ git secrets --install --force ✓ Installed commit-msg hook to .git/hooks/commit-msg ✓ Installed pre-commit hook to .git/hooks/pre-commit ✓ Installed prepare-commit-msg hook to .git/hooks/prepare-commit-msg
AWS アクセスキーのコミットを防ぐ場合
AWS 関連のリポジトリの場合は,デフォルトで用意されている git secrets --register-aws
を使う.そうすると,アクセスキー/アカウントを対象にコミットを防ぐことができる.
$ git secrets --register-aws
--list
オプションで,正規表現などの設定値を確認することができる.secrets.allowed
に入ってる値は example AWS keys
と README.md に書いてあった.
$ git secrets --list secrets.providers git secrets --aws-provider secrets.patterns [A-Z0-9]{20} secrets.patterns ("|')?(AWS|aws|Aws)?_?(SECRET|secret|Secret)?_?(ACCESS|access|Access)?_?(KEY|key|Key)("|')?\s*(:|=>|=)\s*("|')?[A-Za-z0-9/\+=]{40}("|')? secrets.patterns ("|')?(AWS|aws|Aws)?_?(ACCOUNT|account|Account)_?(ID|id|Id)?("|')?\s*(:|=>|=)\s*("|')?[0-9]{4}\-?[0-9]{4}\-?[0-9]{4}("|')? secrets.allowed AKIAIOSFODNN7EXAMPLE secrets.allowed wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
--list
オプションは git config
を参照しているので,直接 git config
を叩いても,同じ情報が確認できる.同じく secrets.allowed
に入ってる値は example AWS keys
だから問題なし.
$ git config -l | grep secrets secrets.providers=git secrets --aws-provider secrets.patterns=[A-Z0-9]{20} secrets.patterns=("|')?(AWS|aws|Aws)?_?(SECRET|secret|Secret)?_?(ACCESS|access|Access)?_?(KEY|key|Key)("|')?\s*(:|=>|=)\s*("|')?[A-Za-z0-9/\+=]{40}("|')? secrets.patterns=("|')?(AWS|aws|Aws)?_?(ACCOUNT|account|Account)_?(ID|id|Id)?("|')?\s*(:|=>|=)\s*("|')?[0-9]{4}\-?[0-9]{4}\-?[0-9]{4}("|')? secrets.allowed=AKIAIOSFODNN7EXAMPLE secrets.allowed=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
実際にアクセスキーをコミットしてみる
正規表現に合致する ABCDEFGHIJKLMN123456
というアクセスキー(サンプル)を README.md に書いてコミットしようとすると,以下のエラーが出てコミットできないようになった.
$ git commit -m'Added access key' README.md:50:ABCDEFGHIJKLMN123456 [ERROR] Matched one or more prohibited patterns Possible mitigations: - Mark false positives as allowed using: git config --add secrets.allowed ... - Mark false positives as allowed by adding regular expressions to .gitallowed at repository's root directory - List your configured patterns: git config --get-all secrets.patterns - List your configured allowed patterns: git config --get-all secrets.allowed - List your configured allowed patterns in .gitallowed at repository's root directory - Use --no-verify if this is a one-time false positive
今回は AWS の例を試したが,--add
オプションを使えば,任意の正規表現も登録できるため,他の SaaS などを使ってる場合などにも簡単に対応できる.
スキャン機能
--scan
オプションを使うと,リポジトリを対象に既にコミットされていないかをスキャンすることができる.
$ git secrets --scan
さらにこのオプションでは git secrets --aws-provider
で取得した ~/.aws/credentials
の値を対象にチェックもしてくれるため,気が利いている.
まとめ
git-secrets は,地味な感じもあるけど,非常に便利なツールだった.AWS としても,誤ってコミットされてしまって事故が起きてしまうことは望んでないだろうし,もっと普及すると良さそう.git-secrets をまだ使ってない人はすぐ使いましょう!