TerraformでIAMユーザーを作成する際にKeybaseを使わずGPG鍵をファイル(Gitリポジトリ)で管理するようにしたのでそのメモ

TerraformでIAMユーザーを作成する機会があったのですが、そのパスワードやシークレットキーを扱うリソースではGPG鍵を渡す必要があるみたいです。
[aws_iam_user_login_profile](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_user_login_profile)
[aws_iam_access_key](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_access_key)

諸事情でKeybaseを使わずにGPG鍵のファイルをリポジトリで管理したのでその記録を残します。
環境はmacOS Catalinaです。

GPG周りを解説するためtfファイルについては割愛します。

# リポジトリで管理する場合のディレクトリ構成例
```text
.
├── backend.tf
├── main.tf
├── provider.tf
├── variable.tf
├── gpg_keys
│   ├── GPGの秘密鍵
│   ├── GPGの公開鍵
│   └── GPGの公開鍵をbase64でエンコードしたもの
├── raw_sensitive_values
│   └── 復号済みのパスワードなどのファイル
└── sensitive_values
    └── 暗号化されたパスワードなどのファイル

```

ディレクトリはこのような形にしました。
実際はIAMポリシーを記載したjsonファイルなどもあるのですが記事を書くにあたって省いています。
また、「GPGの公開鍵」と「GPGの公開鍵をbase64でエンコードしたもの」といったようなほとんど重複した内容のファイルも別で保存しているのは、チーム向けにGPG鍵周りのドキュメントを書く際にコピペ用のコマンドを記載できて便利だからです。

## 事前準備
```
brew install gpg pinentry-mac
```

.zshrcなどに下記を記述

```
GPG_TTY=$(tty)
export GPG_TTY
```

```
source ~/.zshrc
```
などして再読み込み


## GPGのペア鍵を生成
```
gpg --full-generate-key
```

で公開鍵・秘密鍵を生成します。

```
Please select what kind of key you want:
   (1) RSA and RSA (default)
   (2) DSA and Elgamal
   (3) DSA (sign only)
   (4) RSA (sign only)
```
のような画面では1を選択してください。

```
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048) 4096
Requested keysize is 4096 bits
```
のような画面ではデフォルトで良いと思います（私は3072でした）

```
Please specify how long the key should be valid.
         0 = key does not expire
      <n>  = key expires in n days
      <n>w = key expires in n weeks
      <n>m = key expires in n months
      <n>y = key expires in n years
```

のような画面では0を選びました。

```
Real name:
```

では本名を入れます。

```
Email address:
```
では自分のメールアドレスを入れました。

```
Comment:
```
ではなにも入力せずEnterを押しました。

```
Passphrase: 
```
では復号時や鍵のインポート時などで要求されるパスフレーズを設定します。チームが見れるドキュメントなどに記載しておくと良いと思います。

ここまでの作業が終われば鍵は作成されたかと思うので下記コマンドで鍵が作成できたか確認してみてください。

```
gpg --list-keys
```

次にここまでの作業で作成された公開鍵・秘密鍵をファイルに出力します。
先述したディレクトリの例であれば下記コマンドでファイルに鍵を出力できます。

```
gpg -o ./gpg_keys/{任意のファイル名}.public.gpg  --export 入力した本名
gpg -o ./gpg_keys/{任意のファイル名}.private.gpg --export-secret-key　入力した本名
↑このときにパスフレーズを求められます
```
鍵は他の人が復号化する際に場所をわかりやすくするため`gpg_keys`ディレクトリに入れることにしました。

また、TerraformではGPG鍵を使用する際にbase64でエンコードしないといけないので
下記コマンドでエンコードして`gpg_keys`ディレクトリに入れてリポジトリ管理にしました。

```
cat ./gpg_keys/{作成した鍵のファイル名}.public.gpg | base64 | tr -d '\n' > ./gpg_keys/{任意のファイル名}.public.gpg.base64
```

ここまでで作成した
` ./gpg_keys/{任意のファイル名}.public.gpg.base64`ファイルを`gpg_key`としてTarraformリソース(aws_iam_access_keyやaws_iam_user_login_profileなど)に渡して使用してください。

```
例
pgp_key = file("${path.module}/gpg_keys/〇〇.public.gpg.base64")
```

# 暗号化されて表示されるパスワード・シークレットキーを復号してファイルとして保存する
tfファイルの記述・applyまで済ませたら作成されたIAMのパスワードやシークレットキーを復号しファイルとして保存します。

terraform showコマンドでいつでも暗号化された値が出力されるので保存する必要もないかとも思ったのですが、必要になるたびに復号する手間やリソースの数が増えてきた場合に探しにくくなるかもしれない点を考慮しファイルとして保存することにしました。

```
terraform show
```

1. 上記コマンドでTerraformで作成されたリソースの情報が出力されます。
今回はIAMのパスワードとシークレットキーを保存したいので`encrypted_password`と`encrypted_secret`を探します。

2. その結果をコピーしてエディタなどで./sensitive_values/ディレクトリに保存しました。（GPG鍵周りの扱いについてチーム向けのドキュメントを作成する際にコピペ用のコマンドを作りやすくするため）

3. 下記コマンドを参考に復号された値を`./raw_sensitive_values/`ディレクトリに保存してください。 
また、復号する際に秘密鍵のパスワード（パスフレーズ）を求められます。

```保存するファイル名の例：〇〇_encrypted_password.txt```
cat ./sensitive_values/{暗号化されたパスワードorシークレットキーの入ったファイル} | base64 -D | gpg --decrypt | cat > ./raw_sensitive_values/{任意のファイル名}.txt
```
これで生のパスワードとシークレットキーをファイルに保存することができました。

:::note info
Inappropriate ioctl for deviceというエラーが出た場合は事前準備に書いてある.zshrcを記載してsourceで再読み込みしてみてください。
:::

## 他の人が作成した鍵をインポートする
GPGは鍵ファイルを指定して復号することができないので鍵を流用する場合でも他の人が作成した鍵をインポートする必要があります。
既存の鍵を流用する場合は下記のコマンドでインポートしてください。

``` 
gpg --import ./gpg_keys/〇〇/{インポートする鍵ファイル名}.private.gpg
```