git-cryptを使ってlocal.settings.jsonなりシークレットを含むファイルをGitで管理する。(Windows PowerShellを使う編)

## はじめに
これはチーム内の課題であるよく更新されるシークレットを含んだファイルをどのように管理するかを調べた備忘録になります。

前提となっている条件は以下のとおりです。

- Windows 10
- Windows PowerShell
- Microsoft Azure

採用する技術は以下のとおりです。

- git
- GPG
- git-crypt

## この記事で取り扱うこと
- git-cryptをWindows10 , Windows PowerShell で使えるようにする方法。
- git-cryptを使ってGitのリモートリポジトリにローカルリポジトリの一部データを暗号化してPushする方法。

## この記事ではやらないこと
- git-cryptで生成した復号鍵の詳細な取り扱い方法。
- GPG,git-cryptについての説明。

## 手順

### 1回だけやること（＝初期設定）

1. GPGをWindows PowerShellで使えるようにする。
2. git-cryptをWindows PowerShellで使えるようにする。
3. GPGでキーペアを作成する。

### 新しくGitリポジトリを作成するごとにやること
1. 作成したGitリポジトリにgit-cryptを適用する。
2. 実際にCommitしてPushしてみたりして暗号化されているか確認する。
3. 復号用の鍵を生成し、適切な管理場所に保管する。

### git-cryptにより暗号化されたファイルを含むGitリポジトリをCloneするときにすること
1. リポジトリをCloneする。
2. 復号鍵を何かしらの方法で取得し、それっぽいところに配置する。
3. Cloneしたファイルを復号鍵を使って復号化する。

## 1回だけやること（＝初期設定）

### 1. GPGをWindows PowerShellで使えるようにする。

下記リンクよりGPGをダウンロードし、実行しインストールします。
https://www.gnupg.org/download/index.html

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2034469/fc9c9831-7879-77f6-6e97-e6c9e9c6b90a.png)

次にPowerShellで簡単に使えるようにPathを通します。
Windows10であれば設定から検索ウィンドウに「環境変数」と入力すればすぐでてきます。
今回は「環境変数を編集」を選択しましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2034469/e935b3f8-5cf1-1979-5b14-ffa51e2012f8.png)

↓のPathをダブルクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2034469/15eac4aa-b694-0a88-29da-7c9c63094cbc.png)

新規ボタンを押して↓のように入力します（**ここは上記手順のインストール先により変わります**）。
>C:\Program Files (x86)\GnuPG\bin
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2034469/425898cf-6bac-5707-1baa-2b7a74aa333e.png)

入力をしたらOKを押してダイアログを閉じます。

PowerShellを起動し以下のように入力します。
>gpg --version

バージョンが表示されれば設定はOKです。

```
C:\Users> gpg --version
gpg (GnuPG) 2.2.28
libgcrypt 1.8.8
Copyright (C) 2021 g10 Code GmbH
License GNU GPL-3.0-or-later <https://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Home: C:/Users/{user}/AppData/Roaming/gnupg
Supported algorithms:
Pubkey: RSA, ELG, DSA, ECDH, ECDSA, EDDSA
Cipher: IDEA, 3DES, CAST5, BLOWFISH, AES, AES192, AES256, TWOFISH,
        CAMELLIA128, CAMELLIA192, CAMELLIA256
Hash: SHA1, RIPEMD160, SHA256, SHA384, SHA512, SHA224
Compression: Uncompressed, ZIP, ZLIB, BZIP2
C:\Users>
```

（参考: Windows環境でもGitBashであればデフォルトでGPGが入っているようです。)

### 2. git-cryptをWindows PowerShellで使えるようにする。

コチラを利用させていただきます。
https://github.com/oholovko/git-crypt-windows

以下のリンクから git-crypt.exe をダウンロードします。
https://github.com/oholovko/git-crypt-windows/releases

ダウンロードしたらどっかテキトーに配置するのですが以下のディレクトリが設定とか楽のでオススメです。
>C:\Program Files\Git\cmd\git-crypt.exe

**上記手順が終わってから**PowerShellを起動し以下のようにコマンドを打ちます。バージョン情報が見れたらOKです。
>git-crypt --version

```
C:\Users> git-crypt --version
git-crypt 0.6.0
```

### 3. GPGでキーペアを作成する。

PowerShellで以下のコマンドを打ちます。
>gpg --generate-key

このとき
名前
メールアドレス
GPGキーペアを保護するパスフレーズ
の入力が求められますのでそれぞれ入力しましょう。

```

C:\Users> gpg --generate-key
gpg (GnuPG) 2.2.28; Copyright (C) 2021 g10 Code GmbH
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Note: Use "gpg --full-generate-key" for a full featured key generation dialog.

GnuPG needs to construct a user ID to identify your key.

Real name: {Your Name}
Email address: {Your Email}
You selected this USER-ID:
    "{Your Name} <{Your Email}>"

Change (N)ame, (E)mail, or (O)kay/(Q)uit? O
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
gpg: AllowSetForegroundWindow(25028) failed: �A�N�Z�X�����ۂ���܂����B
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
gpg: key A105CE3423E2BD6B marked as ultimately trusted
gpg: revocation certificate stored as 'C:/Users/{user}/AppData/Roaming/gnupg/openpgp-revocs.d\FFF7B23E4D20DE2B4A657E92A105CE3423E2BD6B.rev'
public and secret key created and signed.

pub   rsa3072 2021-12-06 [SC] [expires: 2023-12-06]
      FFF7B23E4D20DE2B4A657E92A105CE3423E2BD6B
uid                      "{Your Name} <{Your Email}>"
sub   rsa3072 2021-12-06 [E] [expires: 2023-12-06]

```

## 新しくGitリポジトリを作成するごとにやること

### 1. 作成したGitリポジトリにgit-cryptを適用する。
作成したリポジトリをCloneしてきたら、そのディレクトリで以下のコマンドを打ちましょう。
>git-crypt init

```
E:\repos\poc-git-crypt-qiita [main ≡]> git-crypt.exe init
Generating key...
```

その後、 「.gitattributes」という名前のファイルを作成します。
（エクスプローラーとかVS Code上とかから作ればいいです。今回はコマンドでやってしまいます。）

```
E:\repos\poc-git-crypt-qiita [main ≡]> New-Item .gitattributes


    ディレクトリ: E:\repos\poc-git-crypt-qiita


Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a----        2021/12/06     19:50              0 .gitattributes
```

.gitattributesファイルが作成できたら中身を開いて編集します。
このファイルの中にPushしたときに暗号化するファイル、ディレクトリを指定します。
この記事では local.settings.json という名前のファイルは暗号化するように設定してみます。
詳しい記法は以下を参照してください。
https://github.com/AGWA/git-crypt#using-git-crypt

``` txt:.gitattributes
local.settings.json filter=git-crypt diff=git-crypt
```

これでgit-cryptの設定はOKです。

### 2. 実際にCommitしてPushしてみたりして暗号化されているか確認する。

上記手順で暗号化する設定をしたファイルを作成します。
（今回比較用に appsettings.json というファイルも作っておきます。）

```json:local.settings.json
{
"secret":"This is Secret"
}
```

```json:appsettings.json
{
"secret":"This is NOT Secret"
}
```

比較用のファイルも作成できたらCommit＆Pushしてみましょう。

```git
E:\repos\poc-git-crypt-qiita [main ≡ +3 ~0 -0 !]> git add .
E:\repos\poc-git-crypt-qiita [main ≡ +3 ~0 -0 ~]> git commit -m init
E:\repos\poc-git-crypt-qiita [main ↑1]> git push
```

Pushした先のリモートリポジトリを確認します。
local.settings.jsonがバイナリ化してリモートリポジトリにPushしてあれば成功です。
（以下に上記手順の踏んだリポジトリのリンクを貼っておきます。）
https://github.com/bory-kb/poc-git-crypt-qiita

### 3. 復号用の鍵を生成し、適切な管理場所に保管する。

今の段階ではリモートリポジトリでバイナリ化したファイルを復号できるのはリポジトリを作成した本人だけなので
ほかのチームメンバーも同様に復号できるように復号鍵を生成します。
PowerShellを起動後、ローカルリポジトリまで移動し、以下のコマンドを打ちます。今回はCドライブ直下に復号鍵を生成します。
（生成先によっては管理者権限が必要になると思います。権限がない場合は適宜生成先を変更してください。）

```
E:\repos\poc-git-crypt-qiita [main ≡]> git-crypt export-key c:\decryption_key.txt
```
**ここで生成した復号鍵はGit管理しないでください！今までやったことが意味なくなります！**

生成した復号鍵はAzure KeyVaultなりAWS KMSなり保管しておいてください。



## git-cryptにより暗号化されたファイルを含むGitリポジトリをCloneするときにすること
### 1. リポジトリをCloneする。
そのままです。Git Cloneしてきます。

### 2. 復号鍵を何かしらの方法で取得し、それっぽいところに配置する。

「新しくGitリポジトリを作成するごとにやること」の手順3で生成された復号鍵がチーム内で適切に管理されているはずです。
復号鍵を取得してきてPC内に配置しましょう。今回はCドライブ直下に配置したとします。

### 3. Cloneしたファイルを復号鍵を使って復号化する。

復号化する前にCloneしてきたディレクトリに移動してみましょう。
local.settings.jsonの中身が見れるでしょうか。おそらくバイナリ化していて（＝暗号化されていて）見れないはずです。
以下の復号化手順の踏み、見られるようにしてみましょう。

PowerShellを起動、Cloneしてきたローカルリポジトリに移動した後、以下のコマンドを打ちます。
（改めてですが取得してきた復号鍵はCドライブ直下に配置したと想定しています。適宜復号鍵のPathは変更してください。）

```
E:\repos\poc-git-crypt-qiita-user2 [main ≡]> git-crypt unlock C:\decryption_key.txt
```

改めてlocal.settings.jsonを見てみましょう。バイナリではなくちゃんと表示されていれば復号化は終了です。

## 大いに参考にさせていただいた記事
https://qiita.com/tmiki/items/5d403025b1f5536423b4#1-2-git-crypt%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB

https://qiita.com/tmiki/items/5d403025b1f5536423b4#%E6%A4%9C%E8%A8%BC%E3%81%97%E3%81%9F%E7%92%B0%E5%A2%83