はじめに
本手順で紹介しているコードは、azu さんが作成したコードから Notion や 1password の利用を取り除いただけのコードです。
本記事を投稿するにあたって、このような利用方法があると視野を広げてくれた azu さんに感謝の言葉を送ります。
Secretlint とは
- Scanner: プロジェクト内の credentials 情報が見つけ報告
- Project Friendly: 簡単にプロジェクトに導入でき、CI サービスにも利用可能
- Pre-Commit Hook: credentials 情報のコミットを防止
- Pluggable: カスタムルールで柔軟な構成の作成が可能
- Documentation: ルールの検出理由を説明
Demo
簡単なデモがありますのでこちらをご覧ください。
導入手順
前提
Secretlint には 2 つの導入手順があります。
一つは Docker を利用する方法です。もう一つは、Node.js を利用する方法です。
Docker を利用する場合、コミットする度にコンテナを起動することになるのでリソースも取られたりとメリットを感じられなかったので Node.js の利用を選びました。Node.js を入れていなかったりこの辺りわからない人であれば、Docker の方が良いかもしれません。
Node.js の場合、現在で必要とされているバージョンは 18+ です。
公式のドキュメントには「グローバルインストールすると、個々のリポジトリに対するカスタマイズができなくなるのでおすすめしない」とありますが、私としてはグローバルに全ての認証情報は弾いて欲しいのでグローバルインストールしたいと思います。
ただプロジェクトによっては nodenv などでバージョンを変えますし、その度 global となる package を認識させるのは手間ですので、特定のディレクトリを作成し、その中に secretlint をインストールし実行させる手法を取りたいと思います。
githooks について
git には githooks という機能が備わっています。core.hooksPath
にデフォルトで $GIT_DIR/hooks
が入ってます。これを任意のディレクトリに書き換えれば、グローバルに githooks を動かせるのですがそれをするとリポジトリ内に定義している githooks を呼び出すことができません。
手順
- hooks を置く特定のディレクトリを作成する
- 作成したディレクトリにて package.json を作成し、secretlint をインストールする
- secretlint の設定をする
- hooks させるコードを展開する
- gitconfig コマンドで hooks させるディレクトリへのパスを指定する
- 動作確認
hooks を置く特定のディレクトリを作成する
ディレクトリを作成してください。
mkdir /path/to/git-hooks
作成したディレクトリにて package.json を作成し、secretlint をインストールする
npm init
して適当なpackage.json
を生成します。
生成できたら、secretlint をインストールします。secretlint 自体には rules が内包されていないためこちらも合わせてインストールします。
npm install secretlint @secretlint/secretlint-rule-preset-recommend
secretlint の設定をする
secretlint に使用するルールを適用するために、.secretlintrc.json
を作成し、コードを適用します。
{
"rules": [
{
"id": "@secretlint/secretlint-rule-preset-recommend"
}
]
}
hooks させるコードを展開する
hooks ディレクトリを作成し、ファイルを生成します。
mkdir hooks
cd hooks
touch _local-hook-exec applypatch-msg commit-msg post-commit post-update pre-applypatch pre-commit pre-merge-commit pre-push pre-rebase pre-receive prepare-commit-msg update
_local-hook-exec
に以下をペースト
#!/bin/bash
declare GIT_ROOT=$(git rev-parse --show-superproject-working-tree --show-toplevel | head -1)
declare HOOK_NAME=$(basename "$0")
declare LOCAL_HOOK="${GIT_ROOT}/.git/hooks/${HOOK_NAME}"
declare LOCAL_HOOK_ALT="${GIT_ROOT}/.githooks/${HOOK_NAME}"
# Prefer project's hook than global hooks
if [ -e "$LOCAL_HOOK" ]; then
$LOCAL_HOOK
export LOCAL_HOOK_IS_CALLED=1
fi
if [ -e "$LOCAL_HOOK_ALT" ]; then
$LOCAL_HOOK_ALT
export LOCAL_HOOK_IS_CALLED=1
fi
pre-commit
に以下をペースト
#!/bin/bash
source $(dirname "${0}")/_local-hook-exec
declare scriptDir=$(cd $(dirname $0) || exit;pwd)
declare parentDir="$(dirname "${scriptDir}")"
declare HAS_NOT_NODE;
# if "NO_SECRET" is defined, skip secretlint
if [[ -n "${NO_SECRET}" ]]; then
exit 0
fi
HAS_NOT_NODE=$(command -v node || echo "not found")
if [[ "${HAS_NOT_NODE}" == "not found" ]]; then
exit 0
fi
# Secretlint
declare FILES
FILES=$(git diff --cached --name-only --diff-filter=ACMR | sed 's| |\\ |g' | sed 's|\[|\\\\[|g' | sed 's|\]|\\\\]|g')
[ -z "$FILES" ] && exit 0
echo " ▶ Check credentials by secretlint"
if [ -f "$PWD/.secretlintignore" ]; then
echo "$FILES" | xargs "${parentDir}/node_modules/.bin/secretlint" --secretlintignore "$PWD/.secretlintignore" --secretlintrc "${parentDir}/.secretlintrc.json"
else
echo "$FILES" | xargs "${parentDir}/node_modules/.bin/secretlint" --secretlintrc "${parentDir}/.secretlintrc.json"
fi
RET=$?
if [ $RET -eq 0 ] ;then
exit 0
else
exit 1
fi
その他全ては下記を書き込みます。
#!/bin/bash
source $(dirname ${0})/_local-hook-exec
が、hooks ディレクトリ内にinit.sh
など任意のファイル名で作成し、以下のコードを実行すると手間がなく良いかと思います。
#!/bin/bash
# 書き込む内容
content="#!/bin/bash
source \$(dirname \${0})/_local-hook-exec"
# 書き込むファイルのリスト
files=("applypatch-msg" "commit-msg" "post-commit" "post-update" "pre-applypatch" "pre-merge-commit" "pre-push" "pre-rebase" "pre-receive" "prepare-commit-msg" "update" )
# 各ファイルに内容を書き込む
for file in "${files[@]}"
do
echo "$content" > "$file"
done
pwd # /path/to/git-hooks/hooks
sh init.sh
権限を付与する
hooks に権限を付与しましょう
pwd # /path/to/git-hooks
chmod -R +x $(pwd)/hooks
gitconfig コマンドで hooks させるディレクトリへのパスを指定する
あらかじめリポジトリのパスに入っておくと設定が楽です。
pwd # /path/to/git-hooks
git config --global core.hooksPath $(pwd)/hooks
.gitconfig
に設定されてるか確認しましょう。
git config --global core.hooksPath
# /path/to/git-hooks/hooks
cat ~/.gitconfig
# [core]
# hooksPath = /path/to/git-hooks/hooks
動作確認
secretlint のデモにもあるこちらをテキストとして保存してコミットしようとしてみてください。
エラーが表示されれば動作しています。
# Secretlint Demo
URL: https://user:pass@example.com
GitHub Token: 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
SendGrid: "SG.APhb3zgjtx3hajdas1TjBB.H7Sgbba3afgKSDyB442aDK0kpGO3SD332313-L5528Kewhere"
AWS_SECRET_ACCESS_KEY = wJalrXUtnFEMI/K7MDENG/bPxRfiCYSECRETSKEY
Slack:
xoxa-23984754863-2348975623103
xoxb-23984754863-2348975623103
xoxo-23984754863-2348975623103
Private Key:
-----BEGIN RSA PRIVATE KEY-----
MIICWwIBAAKBgQCYdGaf5uYMsilGHfnx/zxXtihdGFr3hCWwebHGhgEAVn0xlsTd
1QwoKi+rpI1O6hzyVOuoQtboODsONGRlHbNl6yJ936Yhmr8PiNwpA5qIxZAdmFv2
tqEllWr0dGPPm3B/2NbjuMpSiJNAcBQa46X++doG5yNMY8NCgTsjBZIBKwIDAQAB
AoGAN+Pkg5aIm/rsurHeoeMqYhV7srVtE/S0RIA4tkkGMPOELhvRzGmAbXEZzNkk
nNujBQww4JywYK3MqKZ4b8F1tMG3infs1w8V7INAYY/c8HzfrT3f+MVxijoKV2Fl
JlUXCclztoZhxAxhCR+WC1Upe1wIrWNwad+JA0Vws/mwrEECQQDxiT/Q0lK+gYaa
+riFeZmOaqwhlFlYNSK2hCnLz0vbnvnZE5ITQoV+yiy2+BhpMktNFsYNCfb0pdKN
D87x+jr7AkEAoZWITvqErh1RbMCXd26QXZEfZyrvVZMpYf8BmWFaBXIbrVGme0/Q
d7amI6B8Vrowyt+qgcUk7rYYaA39jYB7kQJAdaX2sY5gw25v1Dlfe5Q5WYdYBJsv
0alAGUrS2PVF69nJtRS1SDBUuedcVFsP+N2IlCoNmfhKk+vZXOBgWrkZ1QJAGJlE
FAntUvhhofW72VG6ppPmPPV7VALARQvmOWxpoPSbJAqPFqyy5tamejv/UdCshuX/
9huGINUV6BlhJT6PEQJAF/aqQTwZqJdwwJqYEQArSmyOW7UDAlQMmKMofjBbeBvd
H4PSJT5bvaEhxRj7QCwonoX4ZpV0beTnzloS55Z65g==
-----END RSA PRIVATE KEY-----
お疲れ様でした。これで認証コードをコミットする前に防げますね。
しかしこれで万全というわけではないので、随時アップデートするようにしましょう。
出典
https://github.com/secretlint/secretlint