245
204

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

git-secretsはじめました

Last updated at Posted at 2018-10-25

はじめに

サーバのID/Passwordをソースにべた書きして開発することは誰しもあるかと思います。しかし先日話題になっていた「AWSから120万円の高額請求が来た話」というQiitaエントリのように、public gitリポジトリにAWSのアクセス情報を置こうものならばあっという間に悪用されてしまいます。

そんな他人に知られると悪用されかねない情報は「他人が容易にアクセス可能な場所に置かないこと」が鉄則なのですが、心掛けだけではどうやってもヒューマンエラーを避けることができません。そこで本エントリでは、そういったヒューマンエラーが起きた際の水際防止策として「gitリポジトリへのアクセス情報(ID/Passwordなど)の含まれたファイルのコミット」を機械的にリジェクトするgit-secretsの使い方を簡単に紹介します。1

Q: git-secretsは何ができる?

A: gitのcommit/commit message等をスキャンし、その中に事前設定した秘密情報が含まれていたら、そのcommitをリジェクトします。

より正確には、

  • git commit時にそのcommitの中に、
  • 任意のタイミングで過去のgit historyの中に、
  • あるいは任意のタイミングで任意のファイルの中に、

事前設定された正規表現にマッチする情報が存在するか否かを検査します。awslabsが中心で開発しているだけあって、何よりもまず、AWSのcredentialの含まれたcommitを弾くのに非常に向いています。

準備

まずはマニュアル通りにインストールします。macOS Xならhomebrewが簡単です。

brew install git-secrets

そうでない場合は、make installです。

$ git clone https://github.com/awslabs/git-secrets.git
$ cd git-secrets
$ make install

基本的な使い方

導入として、最も単純な例として、git commit実行時、そのcommitの中にAWS向けの秘密情報が含まれているか否かを検査する方法を紹介しましょう。

はじめに、新規に立ち上げたgitリポジトリ、あるいは既存のgitリポジトリに対して、git secrets --installを行うことで、当該のリポジトリをgit-secretsに対応させます。

$ git init
$ 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の設定を行います。git-secretsでは、予め用意されているコマンドオプションgit secrets --register-awsを実行することで、自力で細かな設定をすることなくAWS向けのcommit検査設定を導入することができます。

$ git secrets --register-aws

試しにAWSのアクセスキー(ダミー)を入れたファイルを作成、git addしてcommitしてみます。

$ touch secret.txt
$ echo "aws_secret_access_key = ABcDe1F2hIjkl3nop45sTUv6XYz7aBcDEFghIJKL" > secret.txt
$ git commit -a
secret.txt:1:aws_secret_access_key = ABcDe1F2hIjkl3nop45sTUv6XYz7aBcDEFghIJKL

[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

no changes added to commit

無事、リジェクトされました。

なお、上記のエラーメッセージにあるように、一時的に検査を除外してcommitしたい場合にはgit commitコマンドに対して--no-verifyオプションを付与します。また、既存のリポジトリにあとからgit-secretsを対応させた場合、過去のcommit履歴を検査したいことがあるでしょう。その場合は、git secrets --scan-historyを行うことで、git historyをスキャンして検査することができます。まとめて以下に例示します。

git commit -a --no-verify
[master 61d9545] added credential with --no-verify
 1 file changed, 1 insertion(+), 1 deletion(-)

 $ git secrets --scan-history
61d954586149283a4f9ab70355320c15b846aa75:secret.txt:1:aws_secret_access_key = ABcDe1F2hIjkl3nop45sTUv6XYz7aBcDEFghIJKL

[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

無理矢理追加したcommitが正しく検出されました。

検査設定のカスタマイズ

AWS向けの秘密情報の検査設定については便利なショートカットオプションが用意されていますが、他の情報については自力で設定が必要です。設定方法には

  • 正規表現で検出パターンを定義する方法、
  • 秘密情報のファイル(~/.aws/credentialsなど)を読み込み、その内容の各行のexact-matchの検出パターンとして設定する方法、

の2種類があります。

正規表現での検出パターン定義

git-secretsによりAWS向けの秘密情報「以外」を検出したい場合、commitから除外したい秘密情報のフォーマットに応じた正規表現を、ひとつひとつ登録していきます。ここでは、

password="top secret"

のように与えられるパスワードを検出パターンの正規表現 "password\s*=\s*\".+\"$"として登録します。

$ git secrets --add "password\s*=\s*\".+\""

$ echo "password=\"ok my password\"" > password.txt
$ git add password.txt
$ git commit -a
password.txt:1:password="ok my password"

[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

実際に検出できました。

秘密情報ファイルを読み込んだ検出パターン設定

秘密情報ファイルなどを読み込んで、その各行をexact-matchでの検出パターンとして設定する方法も存在します。

$ git secrets --add-provider -- <command to show secret info>
$ git secrets --add-provider -- cat ~/.my.password.list.txt


パスワードが1行ごとに羅列されているようなテキストファイルが存在、あるいは秘密情報を列挙するようなコマンドが存在するようなフレームワーク向けとして有効な手段です。(が、そういった条件に当たったことがなく、あまり利用したことはありません。)

サンプルパスワードなどの例外パターン設定

モックテストなどを行う際、決め打ちのサンプルパスワードを利用することは多いかと思います。本番のパスワードは検査で発見・除外してほしいけど、そういったパスワードまで除外されるちょっと困ります。なので、そういったサンプルパスワードは、検出されてもリジェクトされない例外パターンとして設定します。

前述の例では、正規表現"password\s*=\s*\".+\"$"を検出パターンとして設定していました。このとき、このパターンに引っかかるpassword="my example password"を例外として設定しましょう。

$ git secrets --add --allowed --literal "password=\"my example password\""

$ echo "my example password" > password.txt
$ git add password.txt
$ git commit -a
[master (root-commit) aa9098a] example password
 1 file changed, 1 insertion(+)
 create mode 100644 passowrd.txt

無事commitできました。なお、--add --allowedとする(--literalを抜く)と、例外パターンを正規表現で登録できます。が、例外はあくまで例外ですので、false negative 2 を避けるためにも正規表現などは使わずexact-matchで登録するべきです。

設定状況一覧の表示

現在のgit-secretsの設定状況はgit secrets --listを実行することで一覧できます。参考として、--register-awsオプションで設定される検出パターンは以下の通りです。

$ 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

その他のTIPSとか

ファイルの検査

git-secretsはcommitではなくてファイル実体が除外設定に触れていないか否かの検査をすることも可能です。

$ git secrets --scan secrets.txt // ファイルの検査
$ git secrets --scan secretDir // ディレクトリの検査 **git ls-filesで出てくるものが対象**
$ git secrets --scan -r secretDir // サブディレクトリ内部も含めて検査

端末全体の保護

git secrets --register-aws, --add, --add-providerコマンドに対して、--globalオプションを追加することで、global設定として~/.gitconfigにgit-secretsの除外設定が書き込まれることになります。以降、既存のものも含み、git secrets --installを実行したgitリポジトリに対して、当該のglobal設定がデフォルトで有効化されます。

git secrets --installの省略

git init後のgit secret --installを忘れないために、こちらの記事の通り、

$ git secrets --install ~/.git-templates/git-secrets
$ git config --global init.templatedir '~/.git-templates/git-secrets'

を実行し、git init時のテンプレートを作成しておきましょう。これでgit init実行時にgit secrets --installを実行したことと同じになります。

まとめ

AWS以外の場合、自分で検出パターンを指定するのがちょっとめんどくさいですが、「自分固有の秘密情報を不意に公開しない」という目的3のためにはgit-secretsは非常に有用です。特にAWSの設定については各リポジトリごとではなく、--register-aws --globalで端末全体のglobal設定で保険を掛けるのがいい手かと思います。

ただし、git-secretsさえ使っていれば安心というわけではなく、そもそもそういったファイルをgitリポジトリに追加しないようにすることが最も重要です。githubのREADME.mdにも「git-secretsの--register-awsでは、AWSの秘密情報のパターンはほとんど網羅してるけど全部とは限らないのでgit-secretsはあくまで追加の保険として利用しましょう」と明示的に記載されています。冒頭でも書きましたが、git-secretsのようなツールは、ヒューマンエラーが起きた際の水際防止策と考えておきましょう。

  1. git-secretという似たプロジェクともありますが、こちらはgitリポジトリそのものをgpgで暗号化してアクセス制御しちゃおう、というものです。秘密情報が入ったファイルは.gitsecretというディレクトリに暗号化されて記録されていきます。こちらについても別エントリで紹介予定です。

  2. git-secretsによる検査を通過してしまうが実際は本当のパスワードだったりする場合。

  3. 逆に、秘密情報を他人と共有して利用している場合には、別ルートでその秘密情報の受け渡しが必要となるのでgit-secretsは向いていません。秘密情報入りのgitリポジトリを複数人で共有したい、という場合には git-secret (sなし) が良い手かと思います。

245
204
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
245
204

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?