Gitリポジトリに誤ってAWSアクセスキーなどをコミットしないようにgit-secretsを導入
はじめに
サービスの事項環境として AWS を利用していた場合に特に気をつけなければ行けないのが、AWS のアクセスキーのような「API キー」の類をコミットしてしまうことです。
コードに記述しないように気をつけていたとしても、ひょんな事でコミットしてしまうことがあります。
このようなミスに気付けるように git-secrets を導入してみましょう。
検証環境
$ uname -moi
arm64 unknown Darwin
$ bash -version | head -n 1
GNU bash, バージョン 5.2.15(1)-release (aarch64-apple-darwin22.1.0)
git-secrets とは
git-secrets は、「API キー」だけでなく、パスワードやその他のセンシティブ情報のコミットを防ぐためのツールです。
Git リポジトリに秘匿情報が含まれないように、次のものを監視します。
- コミット
- コミットメッセージ
--no-ff
マージ
上記のいずれかに秘匿情報が含まれていた場合には、 コミットが拒否されるようにできます。
git commit
のタイミングでチェックが実行されるということです 。
インストール
PATH
環境変数に設定されているいずれかのディレクトリ ( echo "$PATH" | sed 's/:/\n/g'
で確認できる ) に配置しておきましょう。
Mac OS 環境で Homebrew が使える場合はかんたんにインストールできます。
$ brew install git-secrets
Linux 環境では make
を利用します。
$ git clone https://github.com/awslabs/git-secrets.git
Cloning into 'git-secrets'...
fatal: unable to access 'https://github.com/awslabs/git-secrets.git/': server certificate verification failed. CAfile: none CRLfile: none
$ cd git-secrets/
$ make install
それ以外の環境へのインストール方法もドキュメントに掲載してくれています。
使い方
※インストールしたばかりですが、ここから注意が必要です 。
※インストールしたばかりですが git-secrets
はリポジトリのコミットを監視してくれません 。
すでに git clone
済みのローカルリポジトリに対しては、次のコマンドを実行し git-secrets を有効にする必要があります。
$ cd /path/to/my/repo
$ 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
$ git secrets --register-aws
OK
git secrets --install
git secrets --install
を実行すると、 .git/hooks
ディレクトリ配下に 3 つのスクリプトが作成されます。
中身を見るとわかりますが、 git secrets
コマンドを実行しています。
$ cat .git/hooks/commit-msg
#!/usr/bin/env bash
git secrets --commit_msg_hook -- "$@"
git secrets --register-aws
git secrets --register-aws
を実行すると、 .git/config
に設定が追加されます。
$ cat .git/config
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
[secrets]
providers = git secrets --aws-provider
patterns = (A3T[A-Z0-9]|AKIA|AGPA|AIDA|AROA|AIPA|ANPA|ANVA|ASIA)[A-Z0-9]{16}
patterns = (\"|')?(AWS|aws|Aws)?_?(SECRET|secret|Secret)?_?(ACCESS|access|Access)?_?(KEY|key|Key)(\"|')?\\s*(:|=>|=)\\s*(\"|')?[A-Za-z0-9/\\+=]{40}(\"|')?
patterns = (\"|')?(AWS|aws|Aws)?_?(ACCOUNT|account|Account)_?(ID|id|Id)?(\"|')?\\s*(:|=>|=)\\s*(\"|')?[0-9]{4}\\-?[0-9]{4}\\-?[0-9]{4}(\"|')?
allowed = AKIAIOSFODNN7EXAMPLE
allowed = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
secrets
セクションが追加された設定になります。
git-secrets
は patterns
として設定された正規表現にマッチしたものをセキュア情報として認識し、警告します。
git secrets --register-aws
は patterns
として AWS に関するアクセスキーやアカウント ID などを検出する正規表現を追加します。
ただし、 alloed
に設定された文字列は例外としてチェック対象外となります 。
動作確認
動作を確認してみます。
セキュアな情報を含んだファイルをコミットしてみます。
# `patterns` に引っかかりそうな文字列を記述したファイルを作成
$ echo "access_key = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" > memo.txt
# 追加
$ git add .
# コミット
$ git commit -m "first commit."
memo.txt:1:access_key = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
[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
エラーが発生し、 git commit
が失敗しました。
チェック対象外のパターンを追加する
ケースは少ないです、どうしてもチェックの対象から除外したい文字列があった場合には、2 つの方法で実現できます。
1. .git/config
に allowed
を追加する
.git/config
に allowed
を追記します。
# コマンドで追記していますが、エディタで編集しても構わない
$ echo -e '\tallowed = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' >> .git/config
# 末尾に追加されていることを確認
$ tail -n 5 .git/config
patterns = (\"|')?(AWS|aws|Aws)?_?(SECRET|secret|Secret)?_?(ACCESS|access|Access)?_?(KEY|key|Key)(\"|')?\\s*(:|=>|=)\\s*(\"|')?[A-Za-z0-9/\\+=]{40}(\"|')?
patterns = (\"|')?(AWS|aws|Aws)?_?(ACCOUNT|account|Account)_?(ID|id|Id)?(\"|')?\\s*(:|=>|=)\\s*(\"|')?[0-9]{4}\\-?[0-9]{4}\\-?[0-9]{4}(\"|')?
allowed = AKIAIOSFODNN7EXAMPLE
allowed = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
allowed = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
先程コミット失敗したファイルをコミットできるようになります。
$ echo "access_key = yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy" > memo.txt
$ git add .
$ git commit -m "first commit."
[master (root-commit) 6d8e2ca] first commit.
l files changed, 1 insertions(+)
create mode 100644 memo.txt
正規表現が利用できるため、より簡潔に記述できます。
今度は git-secrets
を使って .git/config
に対象外パターンを追加してみます。
# y が 40 文字である場合には許可する
$ git secrets --add --allowed 'y{40}'
# 末尾に追加されていることを確認
$ tail -n 5 .git/config
patterns = (\"|')?(AWS|aws|Aws)?_?(ACCOUNT|account|Account)_?(ID|id|Id)?(\"|')?\\s*(:|=>|=)\\s*(\"|')?[0-9]{4}\\-?[0-9]{4}\\-?[0-9]{4}(\"|')?
allowed = AKIAIOSFODNN7EXAMPLE
allowed = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
allowed = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
allowed = y{40}
# memo.txt を編集
$ echo "access_key = yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy" > memo.txt
$ git add .
$ git commit -m "first commit."
[master c673b23] first commit.
1 file changed, 1 insertion(+), 1 deletion(-)
2. .gitallowed
に allowed
を追加する
チームメンバーで共有する場合は、 .gitallowed
というファイルを作成し Git リポジトリ上で管理すると良いでしょう。
# y が 40 文字である場合には許可する
$ echo 'z{40}' >> .gitallowed
# 末尾に追加されていることを確認
$ tail .gitallowed
z{40}
# memo.txt を編集
$ echo "access_key = zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" > memo.txt
$ git add .
$ git commit -m "first commit."
[master 7891bf2] first commit.
1 file changed, 1 insertion(+), 1 deletion(-)
過去のコミット履歴を検査する
git-secrets
導入前のコミットに対してもスキャンを実行したい場合、 git secrets --scan-history
コマンドを使うことができます。
# 先程の対象外リストを削除
$ rm .gitallowed
$ git secrets --scan-history
7891bf20b27a4a6a14d68ffcd221293f2161c572:memo.txt:1:access_key = zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
[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
git secrets --register-aws
を PC 内の全 Git リポジトリに適用
git secrets --register-aws
を各 Git リポジトリで実行するのは面倒です。
git secrets --register-aws
コマンドは .git/config
ファイルに [secrets]
セクションを追加します。.git/config
ではなく ~/.gitconfig
に設定できれば PC 内の全 Git リポジトリに対する patterns
設定を適用できます。
エディタで編集しても良いですが、 git secrets --register-aws --global
コマンドを実行することで ~/.gitconfig
に設定が追加されます。
git secrets --install
を git init
実行時に適用
ローカルの Git リポジトリ内で git secrets --install
コマンドを実行することで、 .git/hooks
にスクリプトが作成されました。
すでに存在しているローカル Git リポジトリに対しては面倒ですが git secrets --install
する必要があります。
けれども今後 git clone
または git init
した Git リポジトリに自動的に .git/hooks
が作成されるようにしておくことができます。
$ git secrets --install ~/.git-templates/git-secrets
$ git config --global init.templatedir '~/.git-templates/git-secrets'
( おまけ ) git-secrets が正しく動作しない場合
僕の PC 環境では、以前は問題なく利用できていたのですが、 2023-01-31 現在正しく動作していませんでした。
今回のエントリをまとめているときに正しく動作していないことに気が付きました 。
$ which git
/opt/homebrew/bin/git
$ git --version
git version 2.43.0
$ grep --version | head -n 3
grep (GNU grep) 3.11
Packaged by Homebrew
Copyright (C) 2023 Free Software Foundation, Inc.
git-secrets
実行スクリプトのコードを解析してみました。
$ which git-secrets
/opt/homebrew/bin/git-secrets
# ファイルを開いて内容を確認
$ vi $(which git-secrets)
内部で git grep
コマンドを実行していましたが、 -E
オプションを指定しています。-E
オプション付きで grep
コマンドを実行した場合、 正規表現内でスペース全般(タブ、空白、改行)を表す \s
が使えません。
かわりに [[:space::]]
という表現が使えます。
加えて、 \\-
の表現に問題があるようで、 \\
を除去し -
とします。
そこで git secrets --register-aws
で生成された .git/config
( --global
オプション付きの場合は ~/.gitconfig
) ファイルの内容を書き換えます。
# はじめは以下のようになっている
$ cat .git/config
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
[secrets]
patterns = (\"|')?(AWS|aws|Aws)?_?(SECRET|secret|Secret)?_?(ACCESS|access|Access)?_?(KEY|key|Key)(\"|')?\\s*(:|=>|=)\\s*(\"|')?[A-Za-z0-9/\\+=]{40}(\"|')?
patterns = (\"|')?(AWS|aws|Aws)?_?(ACCOUNT|account|Account)_?(ID|id|Id)?(\"|')?\\s*(:|=>|=)\\s*(\"|')?[0-9]{4}\\-?[0-9]{4}\\-?[0-9]{4}(\"|')?
# \\\\s を [[:space:]] に変換します
$ sed -i '/patterns/s/\\\\s/[[:space:]]/g' .git/config
$ sed -i '/patterns/s/\\\\-/-/g' .git/config
# Global な設定を変更する場合はこちら
$ sed -i '/patterns/s/\\\\s/[[:space:]]/g' ~/.gitconfig
$ sed -i '/patterns/s/\\\\-/-/g' ~/.gitconfig
$ cat .git/config
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
[secrets]
patterns = (\"|')?(AWS|aws|Aws)?_?(SECRET|secret|Secret)?_?(ACCESS|access|Access)?_?(KEY|key|Key)(\"|')?[[:space:]]*(:|=>|=)[[:space:]]*(\"|')?[A-Za-z0-9/\\+=]{40}(\"|')?
patterns = (\"|')?(AWS|aws|Aws)?_?(ACCOUNT|account|Account)_?(ID|id|Id)?(\"|')?[[:space:]]*(:|=>|=)[[:space:]]*(\"|')?[0-9]{4}-?[0-9]{4}-?[0-9]{4}(\"|')?
ひとこと
以前は正常に動いていた気がしていたのですが、勘違いでしょうか?
ディスカッション
コメント一覧
まだ、コメントがありません