【Talisman】GitHubにおける情報漏えいへの対策

# はじめに
この記事を読んでくださっている皆様は日頃から、GitHubで公開しているリポジトリにソースコードなどをアップロードされているかと思います。
管理しているファイルの中には、アップロードするべきではないファイルも含まれていることでしょう。
また、アップロードするファイルに、公開してはいけない、公開するべきではない単語や文字列が含まれていた、なんてこともあるかもしれません。
拡張子だけならともかく、ファイルの中身までいちいち走査してられないし、そんな時間はないですよね。
そこで、そんな面倒で時間のかかる作業を自動で行ってくれるOSSのアプリケーションである、Talismanを提案します！
![talsiman.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2363269/99f0cbb2-8613-8b77-485e-55a69123fbfb.png)

# Talismanとは
TalismanとはOSS(Open Source Software)のファイルチェックツールです。
Talisman をインストールすると、ファイル名や更新内容から機密性が高いと思われる情報(秘密鍵やパスワードなど)をフィルタリングし、条件に一致した場合、レポートの表示とコミットやプッシュのブロックを実施してくれます。
ちなみにTalismanとは、日本語に訳すと「お守り」という言葉になります。その名の通りお守りの役割を果たしてくれます。
# インストール
## インストール方法
以下のコマンドでインストールします。

```bash
curl -k https://raw.githubusercontent.com/thoughtworks/talisman/master/global_install_scripts/install.bash > /tmp/install_talisman.bash && /bin/bash /tmp/install_talisman.bash
```

以下のエラーが発生した場合、shasumコマンドを実行するために、次に示すコマンドで関連するライブラリをインストールします。

```
/tmp/install_talisman.bash: line 147: shasum: command not found
```

- shasumを利用するためのコマンド  

```bash
sudo yum install perl-Digest-SHA
```
証明書(CA)のエラーが出る場合は/tmp/install_talisman.bash内のすべてのcurlコマンドに-kのオプションを付与します。

エラーを解消し、もう一度インストールを実行する場合は次のコマンドを使用します。

```bash
/bin/bash /tmp/install_talisman.bash
```  

正常にインストールが進むと、対話モードに移行しますので環境設定等の設定を行っていきます。

以下に筆者が行ったものを一例として載せておきます。

```bash
  Setting up talisman binary and helper script in /<your_name>/.talisman
  Setting up TALISMAN_HOME in path


  PLEASE CHOOSE WHERE YOU WISH TO SET TALISMAN_HOME VARIABLE AND talisman binary PATH (Enter option number):
  1) Set TALISMAN_HOME in ~/.bashrc
  2) Set TALISMAN_HOME in ~/.bash_profile
  3) Set TALISMAN_HOME in ~/.profile
  4) I will set it later
  #?

  # ここでは環境変数は.bashrcに記載(1を選択)
  
  Setting up interaction mode

  DO YOU WANT TO BE PROMPTED WHEN ADDING EXCEPTIONS TO .talismanrc FILE?
  Enter y to install in interactive mode. Press any key to continue without interactive mode (y/n):

  # yを選択すると、インタラクティブ(対話)モードの利用ができる状態でインストールされる。
  # nを選択すると、自動でインストールが行われる。終了後の記述は以下。
  Setting up TALISMAN_HOME in /<your_name>/.bashrc
  After the installation is complete, you will need to manually restart the terminal or source /<your_name>/.bashrc file
  Press any key to continue ...
  
  Setting up pre-commit hook in git template directory
  No git template directory is configured. Let’s add one.
  (this will override any system git templates and modify your git config file)

  Git template directory: (/<your_name>/.git-template)
  # enterキーを押下
  # テンプレートのディレクトリが追加される
  
  Setting up talisman hook recursively in git repos
  Please enter root directory to search for git repos (Default: /<your_name>):
  Searching /<your_name> for git repositories
  # enterキーを押下
  # 何もないと何も表示されずに終わる。
```
ターミナルを再起動し、gitのローカルリポジトリ(または上記のテンプレートディレクトリ)に下記のようにシンボリックリンクができていることを確認します。

```bash
<your_repository>/.git/hooks/pre-commit -> /<your_name>/.talisman/bin/talisman_hook_script
```
## 動作確認
上記を確認出来たら、テストとして、標準で検閲できる認証鍵のダミーファイルのコミットを行ってみましょう。
正常にインストールできていれば、コミットの時点でマッチングされて、コミットができないという状態になります。
(※中身の記述がないと通ってしまうことを確認済みなので、何かしら記載すること)

Gitからリポジトリをクローンし、aaa.pemというテスト用のファイルを作成します。

```bash
git clone https://github.com/<your_name>/<your_repository>.git
# 例）
git clone https://github.com/Masa-Yasuno/talisman-test.git

# クローンしたリポジトリのディレクトリに移動します。
cd <your_repository>
# お試しのpemファイルを作成します。
vi aaa.pem
```
```
# 何らかの内容を記載します。
-----BEGIN PRIVATE RSA KEY-----
ABCDEF0123456789
-----END PRIVATE RSA KEY-----
```
作成したら実際にコミットを行いましょう。
このaaa.pemという認証鍵ファイルをコミットしようとしてみると以下のような表示がされます。

```bash
git add aaa.pem
git commit -m 'test'
Talisman Scan: 3 / 3 <-------------------------------------------------> 100.00%

Talisman Report:
+---------+--------------------------------+----------+
|  FILE   |             ERRORS             | SEVERITY |
+---------+--------------------------------+----------+
| aaa.pem | The file name "aaa.pem" failed | high     |
|         | checks against the pattern     |          |
|         | ^.+\.pem$                      |          |
+---------+--------------------------------+----------+


If you are absolutely sure that you want to ignore the above files from talisman detectors, consider pasting the following format in .talismanrc file in the project root

fileignoreconfig:
- filename: aaa.pem
  checksum: dd6209adca4e313bc4c352ae1504e0b8cf084052aa5ec04bc1f29bb31ddaa0ef
version: ""

```
ここで、このマッチして弾かれたファイルをコミットできるようにしたい場合、.talismanrcというファイルを作成し、そこに記述する必要があります。

```bash
# .talismanrcというファイルを新規作成
vi .talismanrc
```
```yaml:.talismanrc
# 上記の動作確認の時に得られた設定を書き込む。
fileignoreconfig:
- filename: aaa.pem
  checksum: dd6209adca4e313bc4c352ae1504e0b8cf084052aa5ec04bc1f29bb31ddaa0ef
```
書き込んだら保存して閉じます。
そしてコミット前に、次のコマンドを実行します。

```bash
echo ".talismanrc" >> .gitignore
```
このコマンドを実行することにより、.talismanrcがGitHubにコミットされてしまうことを防ぐことができます。
せっかくTalismanでマッチングさせていても、マッチングさせるためのファイルが公開されてしまっては元も子もないですよね。(.gitignoreをコミットすること)
これで、再度同じファイルをコミットすると、Talismanは検知をしなくなります。
# 検出ルールの追加(カスタムパターン) 
## カスタムパターンとは
TalismanはSSHキー、認証トークン、秘密キーといった機密情報を検知するために事前に定義されたパターン情報を持っています。
しかし、Talismanで事前に定義されているパターン情報以外にも、テストで使う人名やプロジェクト名といった公開したくない情報に対しても対策が必要です。
そのような場合にユーザがさらにパターンを追加するための仕組みがカスタムパターンです。
カスタムパターンは正規表現を使うことでファイル名とコミット内容をチェックします。
## カスタムパターン作成
Gitからリポジトリをクローンします。

```bash
git clone https://github.com/<your_name>/<your_repository>.git
# 例）
git clone https://github.com/Masa-Yasuno/talisman-test.git
```
プロジェクトディレクトリの直下に下記のファイルがあります。
ない場合は作成してください。

```bash
# クローンしたリポジトリのディレクトリに移動します。
cd <your_repository>

# Talismanの設定を編集します。
vi .talismanrc

# 下記の内容を追加します。
# 記述例）
custom_patterns: 
- "[tT][aA][lL][iI][sS][mM][aA][nN]"
```
設定ファイルの全文は下記のとおりです。

```yaml:.talismanrc
custom_patterns:
- "[tT][aA][lL][iI][sS][mM][aA][nN]"

fileignoreconfig:
- filename: aaa.pem
  checksum: dfd392221a7a58282649b0adbb8d87cd4e3152f3652a9e449f6b6f1787454a96
```
上記の例では大文字小文字を問わずにマッチングを行える正規表現を記載しています。
yaml形式であり、:や-の後にはスペースを挿入する必要があります。
## カスタムパターンの動作確認
上記の例を含めたいくつかのパターンを.talismanrcに記載して、実際に動作を確認していきましょう。
.talismanrcに以下を追記します。

```yaml:.talismanrc
custom_patterns:
- "[nN][gG]"
- "[qQ][iI][iI][tT][aA]"
- "[gG][iI][tT][hH][uU][bB]"
```

上記を記載後の.talismanrcの全文は下記のとおりです。

```yaml:.talismanrc
custom_patterns:
- "[tT][aA][lL][iI][sS][mM][aA][nN]"
- "[nN][gG]"
- "[qQ][iI][iI][tT][aA]"
- "[gG][iI][tT][hH][uU][bB]"

fileignoreconfig:
- filename: aaa.pem
  checksum: dd6209adca4e313bc4c352ae1504e0b8cf084052aa5ec04bc1f29bb31ddaa0ef
```

実際に動作させた結果が以下です。この例では、talisman.txtというtxtファイルに上記のパターンに該当する文字列を記載(下記)して、コミットさせたときの結果です。

```text:talisman.txt
TALISMAN
Qiita
GitHub
```

```bash
Talisman Scan: 3 / 3 <--------------------------------------------------------------------------------------------------> 100.00%

Talisman Report:
+--------------+--------------------------------+----------+
|     FILE     |             ERRORS             | SEVERITY |
+--------------+--------------------------------+----------+
| talisman.txt | Potential secret pattern :     | high     |
|              | TALISMAN                       |          |
+--------------+--------------------------------+----------+
| talisman.txt | Potential secret pattern :     | high     |
|              | Qiita                          |          |
+--------------+--------------------------------+----------+
| talisman.txt | Potential secret pattern :     | high     |
|              | GitHub                         |          |
+--------------+--------------------------------+----------+


If you are absolutely sure that you want to ignore the above files from talisman detectors, consider pasting the following format in .talismanrc file in the project root

fileignoreconfig:
- filename: talisman.txt
  checksum: 5e3df1477dbe50ef186a7a883ad3a171f0ed3cc78cfc4ac1fcfadbdc7d154480
version: ""

Talisman done in 10.615396ms
```
talisman.txtの内容を下記のように修正します。

```text:talisman.txt
NG
nG
Ng
ng
```

```bash
Talisman Scan: 3 / 3 <--------------------------------------------------------------------------------------------------> 100.00%

Talisman Report:
+--------------+-------------------------------+----------+
|     FILE     |            ERRORS             | SEVERITY |
+--------------+-------------------------------+----------+
| talisman.txt | Potential secret pattern : NG | high     |
+--------------+-------------------------------+----------+
| talisman.txt | Potential secret pattern : nG | high     |
+--------------+-------------------------------+----------+
| talisman.txt | Potential secret pattern : Ng | high     |
+--------------+-------------------------------+----------+
| talisman.txt | Potential secret pattern : ng | high     |
+--------------+-------------------------------+----------+


If you are absolutely sure that you want to ignore the above files from talisman detectors, consider pasting the following format in .talismanrc file in the project root

fileignoreconfig:
- filename: talisman.txt
  checksum: cca678356509586fa0b79d9a4fff932c7796bb811f19ec22941c55f31a117067
version: ""
```

# ファイル除外設定
上記のように、指定したパターンの文字列をマッチングし、警告ともに表示してくれます。
しかし、下記のように指定した文字列が含まれている別の文字列でも、Talismanはマッチングしてしまいます。
試しにtalisman.txtにdoingとだけ記載してコミットしてみましょう。すると下記のような警告が表示されます。

```text:talisman.txt
doing
```

```bash
Talisman Scan: 3 / 3 <--------------------------------------------------------------------------------------------------> 100.00%

Talisman Report:
+--------------+-------------------------------+----------+
|     FILE     |            ERRORS             | SEVERITY |
+--------------+-------------------------------+----------+
| talisman.txt | Potential secret pattern : ng | high     |
+--------------+-------------------------------+----------+


If you are absolutely sure that you want to ignore the above files from talisman detectors, consider pasting the following format in .talismanrc file in the project root

fileignoreconfig:
- filename: talisman.txt
  checksum: e57fbe08dbfc93f7c2b52379fc166814c33b7192224a7cead5422316353e72a8
version: ""
```
この場合ngという文字列はコミットせず、doingという文字列はコミットされるべきなのですが、文字列の中にngが含まれてしまっているため警告が表示されています。
そのようなときは、talismanのチェックの結果の一番下に記載されている以下のような文言を.talismanrcに記載することで、一度弾かれたファイルを弾かれないようにすることができます。


```yaml:.talismanrc
fileignoreconfig:
- filename: talisman.txt
  checksum: e57fbe08dbfc93f7c2b52379fc166814c33b7192224a7cead5422316353e72a8
version: ""
```
追加した後の.talismanrcは下記のようになります・

```yaml
custom_patterns:
- "[tT][aA][lL][iI][sS][mM][aA][nN]"
- "[nN][gG]"
- "[qQ][iI][iI][tT][aA]"
- "[gG][iI][tT][hH][uU][bB]"

fileignoreconfig:
- filename: aaa.pem
  checksum: dd6209adca4e313bc4c352ae1504e0b8cf084052aa5ec04bc1f29bb31ddaa0ef

- filename: talisman.txt
  checksum: e57fbe08dbfc93f7c2b52379fc166814c33b7192224a7cead5422316353e72a8
```
また以下のコマンドを実行することで、下記のように、プロジェクトのディレクトリの配下にある特定の拡張子のファイルすべてを除外するといったことも可能です。

```bash
talisman --checksum="*.txt"

.talismanrc format for given file names / patterns
fileignoreconfig:
- filename: '*.txt'
  checksum: 71161cf546d81fb70d40e4035f79d010ae996b36f0399769e57117a65817782e
version: "1.0"
```

- インタラクティブモードについて  
インストール時にyes、またはインタラクティブモードを設定すると対話式での実行となります。上記に挙げた例外の登録などを自動で行ってくれるため、こちらの方が便利かもしれません。あとから設定を変更する場合は下記のように.bashrcの内容を書き換えます。

```bash
export TALISMAN_INTERACTIVE=false #となっているので
export TALISMAN_INTERACTIVE=true # に変更する
# または
talisman -i -g pre-commit
# とすることで一時的にインタラクティブモードにできる
```
bashrcを書き換えた場合はターミナルの再起動を忘れないでください。

# Talisman でコミットできない場合(強制コミット)
.talismanrcに記載して、除外しているのに引っかかる場合の最終手段は下記コマンドとなります。
しかし、このコマンドはTalismanが出す警告を無視するものでありますので、除外したいファイルをきちんと設定しているのにも関わらずブロックしてしまう場合にのみ使用するようにしてください。

```bash
git commit -m 'コミット' --no-verify
```

# まとめ
Talismanの使い方について記載していきました。これがあれば情報漏えいは大丈夫！というわけではありませんのであしからず。最後は人の目によるチェックが必要です。あくまで「お守り」程度に思っておくとピンチの時に力を発揮してくれるかもしれません。
皆さんもぜひ一度利用してみてください。
# 参考文献
[Talisman(公式サイト)](https://thoughtworks.github.io/talisman/#home)
[[ThoughtWorks] Talismanでキー情報が含まれたファイルの公開を防ぐ](https://dev.classmethod.jp/articles/talisman/)