Windowsでgit-secretsを利用する

[git-secrets](https://github.com/awslabs/git-secrets) は [AWS Labs](https://github.com/awslabs)で提供されているツールの一つです。

※`AWS Labs`はawsが提供しているツールなりスクリプトなりが置いてある場所


`git-secrets`を利用する事により、AWSアクセスキー、AWSシークレットキーをgitリポジトリにコミットできないようにコミット直前にチェックできるようになります。

他にもファイルを検索したり、独自のルールを設定したい色々と機能があります。

今回はそんな`git-secrets`をWindows環境にインストールして利用してみます。

## 余談

`git-secrets`って昔はREADMEにWindows環境へのインストール方法が書いてなくてWindowsで使えないのかと思ってましたが。

[Writing instructions for how to get git-secrets to work for Windows #87](https://github.com/awslabs/git-secrets/pull/87) 

上記でWindows環境への導入方法が追加されてから、今現在はインストール用のPowerShellスクリプトも用意されています。

## Windows環境に`git-secrets`をインストールしてみる

[Installing git-secrets - Windows](https://github.com/awslabs/git-secrets#windows)

インストール用のPowerShellスクリプト（`install.ps1`）が用意されているのでコチラを実行します。
前提条件として`git`がインストールされていて、PowerShellスクリプトが実行できるようになっている必要があります。

下記のコマンドをPowerShellで実行して下さい。

```PowerShell:【PowerShell】git-secretsのインストール
git clone https://github.com/awslabs/git-secrets
#　このスクリプト。install.ps1があるディレクトリをカレントディレクトリにして実行しないと動かないのでcdする。
cd git-secrets 
./install.ps1
```

スクリプトが正常終了すればインストールは完了です。

ちなみにスクリプトが何をやっているかといえば、

`%USERPROFILE%/.git-secrets`に`git-secrets`と`git-secrets.1`をコピーして、`%USERPROFILE%/.git-secrets`を環境変数`PATH`に追加しています。

## `git-secrets`を利用できるようにリポジトリに`git hook`を設定する

`git-secrets`をインストールしただけではコミット時に認証情報が含まれているかチェックしてくれない状態です。

これは`git-secrets`が`git hook`の機能を利用してチェックをおこなっているためです。

チェックするためには、対象となるリポジトリに`git hook`をインストールする必要があります。

ここでは`check-rep`というリポジトリを作成して、このリポジトリに対して`git hook`をインストールしてAWSシークレットキーがコミットされたかチェックしてみます。

まずはリポジトリに`git hook`をインストールして、`git secrets --list`で`git secrets`の設定を確認してみます。

```PowerShell:【PowerShell】リポジトリの初期化とgithookのインストール
# gitリポジトリの初期化
git init check-rep
cd ./check-rep 

# git hookのインストール
git secrets --install

# aws認証情報用のパターンをgitconfig（ローカル）に書き込み）
git secrets --register-aws

# リポジトリに設定されているsecretsのconfigを表示
git secrets --list
```

`git secrets --list`を実行すると事前登録されているパターンで下記設定が表示されるかと思います。

```text:git_secrets_--listの表示
secrets.providers git secrets --aws-provider
secrets.patterns (A3T[A-Z0-9]|AKIA|AGPA|AIDA|AROA|AIPA|ANPA|ANVA|ASIA)[A-Z0-9]{16}
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
```

この情報がどこに登録されているかといえば、該当リポジトリの`git config --local --list`を見ればみつかります。
眺めているとなんとなく想像はつきますが、アクセスキー、シークレットキーと判断するためのパターンが設定されています。

一点注意なのは、よくドキュメントでサンプルとして利用されている

- アクセスキー`AKIAIOSFODNN7EXAMPLE`
- シークレットキー`wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY`

は`secrets.allowed`として許可設定に含まれているため。

`git secrets`の動作を確認する用途として、このサンプルアクセスキーを利用してしまうと。
許可設定されているので普通にコミットできてしまう点は認識しておく必要があります。

## `git hook`を設定したリポジトリにシークレットキー（サンプル）をコミットしてみる

先程、AWSアクセスキーシークレットキーを判断するパターンを確認しました。
この条件に引っかかるようなシークレットキーをファイルに書き出してコミットしてみます。

※今回は`"aws_secret_access_key = GitSecretsCommitTestCaseSampleKeysSample"`

```PowerShell:【PowerShell】シークレットキーをコミットする
# さきほど設定したリポジトリにサンプルファイルを作成
New-Item -Name ./secret -Value "aws_secret_access_key = GitSecretsCommitTestCaseSampleKeysSample"

git add ./secret
git commit -m test
```

`git commit` を実行した段階で下記のエラーが表示されて`git commit` が阻害されている事がわかります。

```text:コミット時のエラーメッセージ
[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`のAWSアクセスキーとシークレットキーのチェック機能が追加された事が確認できました。

## テンプレートに登録してリポジトリの初期化時に`git hook`のインストールを自動で実行するようにする

リポジトリごとに毎回`git hook`をインストールしてもよいのですが、`git cofing`で用意されている`init.templateDir`にテンプレート登録することで、`git init`、`git clone`時に自動的に`git-secrets`用の`git hook`をインストールする事ができます。

※2021年10月現在の注意点

この手順で利用するコマンドについて。

`コマンドプロンプト`　と `Windows PowerShell` で `git secrets --install ~/.git-templates/git-secrets`がうまく動かない事を確認しています。

ですのでここでのコマンド`Git for Windows`をインストールしたときについてくる`Git Bash`を利用して実施して下さい。

```bash:【GitBash】リポジトリ初期化時に自動でインストールするようにテンプレート設定
# 下記はGitBashで実行して下さい
# 前回はリポジトリごとにgit config（ローカル）を設定していましたが globalをつけて git config(グローバル)に設定を書き込み
git secrets --register-aws --global

# テンプレートファイルを生成
git secrets --install ~/.git-templates/git-secrets

# git configのinit.templateDirに生成したテンプレート使うように設定
git config --global init.templateDir ~/.git-templates/git-secrets
```

上記のコマンドを実行することで、シークレットチェック用のパターンを`git config（グローバル）`に設定し、どのリポジトリでも同様の設定を利用するようにしています。

また`git config（グローバル）`の`init.templateDir`にテンプレートを設定することによりリポジトリ初期化時に`~/.git-templates/git-secrets`をテンプレートとして利用するように登録しています。

ここまでの設定したあとにリポジトリ初期化を実行すると、自動で`git hook`がインストールされている事を確認できます。

```PowerShell:【PowerShell】
git init check-rep
cd ./check-rep 

New-Item -Name ./secret -Value "aws_secret_access_key = GitSecretsCommitTestCaseSampleKeysSample"

git add ./secret
git commit -m test
```

コミット時にチェックエラーが表示される事を確認できるかと思います。

### `git secrets --install ~/.git-templates/git-secrets`がWindows環境ではバグってる

2021年10月現在。

`git secrets --install ~/.git-templates/git-secrets`コマンドを実行して`git-secrets`用のテンプレートを生成しますが。

`コマンドプロンプト`と`Windows PowerShell`で実施すると期待を裏切り。

カレントディレクトリに `~/.git-templates/git-secrets` というテンプレートを作成します。

ホームディレクトリにテンプレートを作成しないで~（チルダ）というフォルダの下にテンプレートファイルを作成してしまう……

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/79b1cd75-bc09-cdde-9dec-678b1afa8008.png)

これはなかなかに残念な感じ。

試した所、`Git Bash`だと問題なくホームディレクトリにテンプレートを作成してくれますが。
`コマンドプロンプト`、`Windows PowerShell`、`Git CMD`だとうまく動かないようです。

[template install fails on Windows #123](https://github.com/awslabs/git-secrets/issues/123)

`PowerShell 7`の場合は、試験的な機能`PSNativePSPathResolution`を利用すれば問題なさそうですが、PowerShell 7.3からは試験的な機能`PSNativePSPathResolution`は削除されました。

## `git hook`の設定を解除する

一度`git-secrets`で管理するように設定したリポジトリを`git-secrets`の管理から外したい場合は`git hook`の設定を削除する必要があります。

`git secrets`のコマンドからアンインストールできれば便利そうですが、現状ではマニュアルでファイルを削除して対応する方法しかないようです。

- [feature request: uninstall](https://github.com/awslabs/git-secrets/issues/95)
- [Add Remove command to remove patterns that were added #125](https://github.com/awslabs/git-secrets/issues/125)

### 対象リポジトリから`git hook`を削除する場合

対象リポジトリの下記3ファイルを削除すれば問題ないようです。

- .git/hooks/commit-msg
- .git/hooks/pre-commit
- .git/hooks/prepare-commit-msg

気になるようだったら`git config（ローカル）`に追加した`secrets.*`な設定も削除して下さい。


### テンプレート登録を解除する場合

`git secrets --register-aws --global`でグローバルに設定して、`init.templateDir`にテンプレート登録を実施し、自動でgit hookをインストールしている場合は下記方法で解除できます。

1. `git config(グローバル）`に書き込んだ`secrets.*`な設定の削除
2. `git config(グローバル）`に書き込んだ`init.templateDir`な設定の削除
3. `~/.git-templates`の削除

`git config --global --edit`を実行するとエディタが起動するので、直接`gitconfig`のパラメータを更新することができます。

こちらから登録した`secrets.*`のパラメータと`init.templateDir`を削除して下さい。
最後に、テンプレートファイル`~/.git-templates`も削除すれば完了です。

もしくは`git config`のグローバルな設定は`~/.gitconfig`ファイルに書き込まれているためこのファイルから`secrets.*`、`init.templateDir`な設定を削除して下さい。

あと`git config --global --unset`,`git config --global --unset-all`コマンドにパラメータ名をそれぞれ渡す方法でも削除できます。

```text:【削除対象】gitconfigの設定
[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
[init]
        templateDir = C:/Users/Administrator/.git-templates/git-secrets
```

## git secrets --scan

今まではコミット時にチェックを実施していましたが。
`git secrets --scan` を利用することにより、ファイルに対してチェックを実施できます。

```PowerShell:scna
# リポジトリ中で実行すればリポジトリのファイル全スキャン
git secrets --scan
# ファイル名を指定すれば対象のみをスキャン
git secrets --scan ./secret
# `git secrets --scan -`とすれば下記のような事もできる
Write-Output 'aws_secret_access_key = GitSecretsCommitTestCaseSampleKeysSample' | git secrets --scan -
```

## 総評

今回は紹介していませんが、`git-secrets`には自分でプロバイダを追加して、指定したルールでファイルをチェックする機能を提供しており。

設定さえすればAWSアクセスキー、シークレットキーに限らず、特定の機密情報のコミットを防ぐような事も実現できます。

一度設定したリポジトリを対象から外す際は、リポジトリの`git hook`設定を元に戻したりと少し戸惑うかもしれませんが。

便利に利用できるツールになるかと思います。