sopsでのクレデンシャル管理【Tips】

# TL; DR
Terraformなどで秘匿情報を扱う際に、`lifecycle { ignore_changes = ["hogehoge"] }`などで管理から外していたりすることがあります。基本的には問題ないと思うのですが、DBのパスワードなど秘伝のタレ化しがちです。折角のコード化なのでこれらも一緒に管理できるとちょっとだけ幸せになれると思います。
そこで[**sops**](https://github.com/mozilla/sops)というmozilla社の開発している`暗号化/復号化`ツールがあります。これを用いてクレデンシャル管理も一緒にやり、少しだけ幸せになろうというTipsです。

# Install
Macユーザーならおなじみ`brew`でインストール可能です。
goがインストール済みであれば`go get`でもインストール可能です。
わたしは`brew`でインストールしました。

```bash:install&nbsp;sops
$ brew install sops
==> Downloading https://homebrew.bintray.com/bottles/sops-3.5.0_1.catalina.bottle.tar.gz
Already downloaded: /Users/Library/Caches/Homebrew/downloads/fa1e1ceaec6d966efe2c08d9d4eae6b27d01f616d9d7043f2545f8075268c7ac--sops-3.5.0_1.catalina.bottle.tar.gz
==> Pouring sops-3.5.0_1.catalina.bottle.tar.gz
🍺  /usr/local/Cellar/sops/3.5.0_1: 7 files, 27.9MB

$ sops --version
sops 3.5.0 (latest)
```

```bash:go&nbsp;install
$ go get -u go.mozilla.org/sops/v3/cmd/sops
$ cd $GOPATH/src/go.mozilla.org/sops/
$ git checkout develop
$ make install

# Makefileのinstall
$ cat Makefile | grep "install:" -A 3
install:
	$(GO) install go.mozilla.org/sops/v3/cmd/sops

tag: all
```

# 暗号鍵
sopsを利用するに当たって暗号化に利用する鍵が必要になります。
PGPを利用するか、以下のクラウドサービスの鍵を利用することが可能です。
対象の鍵はオプションもしくは変数として呼び出すことができるため適宜利用してください。

|対象|サービス名|オプション|変数名|
|---|---|---|---|
|PGP|-|`--pgp`|`SOPS_PGP_FP`|
|GCP|[Cloud Key Management Service](https://cloud.google.com/kms)|`--gcp-kms`|`SOPS_GCP_KMS_IDS`|
|Azure|[Key Vault](https://docs.microsoft.com/ja-jp/azure/key-vault/)|`--azure-kv`|`SOPS_AZURE_KEYVAULT_URLS`|
|AWS|[Key Management Service](https://docs.aws.amazon.com/ja_jp/kms/latest/developerguide/overview.html)|`--kms`|`SOPS_KMS_ARN`|

必要な環境に応じて用意してください。


# 使い方
ざっとした使い方ですので参考までに見てもらえるといいかと思います。
筆者はAWS KMSを用いて実施しました。
※ あらかじめ`export SOPS_KMS_ARN="arn:aws:kms:ap-northeast-1:123456789012:key/hogehoge"`を入力して環境変数に入れています。


## 新規作成
ファイルが無い状態で`sops ファイル名`と入力するとエディタが開かれ下記のようなサンプルが表示されます。

```bash:sops&nbsp;new&nbsp;file
$ sops sample_secret.yml

hello: Welcome to SOPS! Edit this file as you please!
example_key: example_value
# Example comment
example_array:
- example_value1
- example_value2
example_number: 1234.5679
example_booleans:
- true
- false
```

試しに下記のように編集してみました。

```bash:edited&nbsp;file
example_key: example_value
example_number: 1234.5679
```

これを保存して抜けるともう暗号化されています。

```yaml:sample_secret.yml
example_key: ENC[AES256_GCM,data:D9pPc7dRd6PuoLUPPw==,iv:zWZxW42YhJsETnWCfgDnIQL55iTSxNrthVmB5gC4bJI=,tag:E/6EBAQ/MnLbCpGCOSnFHg==,type:str]
example_number: ENC[AES256_GCM,data:93sOpzQJvu4N,iv:aigNbYXg+2uSB7cB+JEOnCguBea49DjU2eSGyaBJM5I=,tag:Kf//or7XpUmPChrdhx4Idg==,type:float]
sops:
    kms:
    -   arn: arn:aws:kms:ap-northeast-1:123456789012:key/890hoge1-67ho-34ga-01fu-1234hoge567
        created_at: '2020-03-10T08:12:15Z'
        enc: AQICAHjzJdn8BrQ9cSoqu5NVOLqeyLNJxw4Gm2+8UkJCyqr6ngHoCN1jRMUoKeYuz1ybQhRDAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQM10R9JpvAo2TpWegYAgEQgDte4OJEdbpEmI0pyuZ6Wmz3qvNtw4TJv7TfEujHIpkf6g9Kapq3wEoETiqjy2z+CYt2VptB9+fQZ3h0hQ==
        aws_profile: ""
    gcp_kms: []
    azure_kv: []
    lastmodified: '2020-03-10T08:33:14Z'
    mac: ENC[AES256_GCM,data:JDiJlMegTqzPRbG2hlcAziRToXhwoz9q8g5d2e0X/8B/sP8T8a+/Z9EhOprsBO8T/S7LaC2pAgOevYXonn906VouY+Kn/8kDGyYFU9qAr50gUJ1DZApCUneM58uKUYIhdo0+erKO7594+hSbbf0Ny9Br1ldPmlHf/TkJ1UtN87o=,iv:qpZQ3fxYXijrKd5u9uXDg+2eOx6hxZv909VZCislKbk=,tag:T+77DkwadQp0YhYf69PXbQ==,type:str]
    pgp: []
    unencrypted_suffix: _unencrypted
    version: 3.5.0
```

## 復号化
上記で作成したファイルを復号化してみます。
`-d`オプションをつけるだけなので非常に簡単です。

```bash:decryption
$ sops -d sample_secret.yml
example_key: example_value
example_number: 1234.5679
```

## シークレットの追加
新規同様`sops ファイル名`で開いて追加するだけです。

```bash:add&nbsp;secret
$ sops sample_secret.yml

example_key: example_value
example_number: 1234.5679
additional: value_add
```
これで保存して確認すると、

```yaml:sample_secret.yml
example_key: ENC[AES256_GCM,data:D9pPc7dRd6PuoLUPPw==,iv:zWZxW42YhJsETnWCfgDnIQL55iTSxNrthVmB5gC4bJI=,tag:E/6EBAQ/MnLbCpGCOSnFHg==,type:str]
example_number: ENC[AES256_GCM,data:93sOpzQJvu4N,iv:aigNbYXg+2uSB7cB+JEOnCguBea49DjU2eSGyaBJM5I=,tag:Kf//or7XpUmPChrdhx4Idg==,type:float]
additional: ENC[AES256_GCM,data:KCkWJ7gd9GHV,iv:RaAhQzuRckK6jaXBTl9lgk0YEs3RHS7xxozOgfTtXPo=,tag:sfi7QStVN5BMy/SGX5RO6Q==,type:str]
sops:
    kms:
    -   arn: arn:aws:kms:ap-northeast-1:123456789012:key/890hoge1-67ho-34ga-01fu-1234hoge567
        created_at: '2020-03-10T08:12:15Z'
        enc: AQICAHjzJdn8BrQ9cSoqu5NVOLqeyLNJxw4Gm2+8UkJCyqr6ngHoCN1jRMUoKeYuz1ybQhRDAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQM10R9JpvAo2TpWegYAgEQgDte4OJEdbpEmI0pyuZ6Wmz3qvNtw4TJv7TfEujHIpkf6g9Kapq3wEoETiqjy2z+CYt2VptB9+fQZ3h0hQ==
        aws_profile: ""
    gcp_kms: []
    azure_kv: []
    lastmodified: '2020-03-10T08:42:48Z'  # 更新されていることがわかる
    mac: ENC[AES256_GCM,data:JDiJlMegTqzPRbG2hlcAziRToXhwoz9q8g5d2e0X/8B/sP8T8a+/Z9EhOprsBO8T/S7LaC2pAgOevYXonn906VouY+Kn/8kDGyYFU9qAr50gUJ1DZApCUneM58uKUYIhdo0+erKO7594+hSbbf0Ny9Br1ldPmlHf/TkJ1UtN87o=,iv:qpZQ3fxYXijrKd5u9uXDg+2eOx6hxZv909VZCislKbk=,tag:T+77DkwadQp0YhYf69PXbQ==,type:str]
    pgp: []
    unencrypted_suffix: _unencrypted
    version: 3.5.0
```
これで簡単にクレデンシャルを追加できます。

## ファイルからリダイレクト
複数あってめんどくさい場合はリダイレクトする形で吐き出してあげましょう。

```bash:
$ cat new_file.yml
simple: yaml_file
add: fromfile
test: encryption
$ 
$ sops -e new_file.yml > enc_new_file.yml
$ 
$ ll enc_new_file.yml
-rw-r--r--  1 staff  staff  1252  3 10 17:49 enc_new_file.yml
```
確認すると、

```yaml:enc_new_file.yml
simple: ENC[AES256_GCM,data:jdgFlc05BALm,iv:n4jexuOttomE2Rr/rfUfgdtO79b/AkMg1+id/P6q5Oc=,tag:0t4rwKW/emWymw8TYQjTeg==,type:str]
add: ENC[AES256_GCM,data:qjYDDU4x4yU=,iv:KBlpm+WFZcHIlHtdMLJljRWxoTIdjR8aEuQ/PQzTLBs=,tag:LaE8tXuQskvknUUdftH/MA==,type:str]
test: ENC[AES256_GCM,data:eA5R4hRAYK/erQ==,iv:qkrpdBxWUNI6lJEuQcxfDsIL3mCWEIHlVUhZ6P4Fdsg=,tag:KJI97tTgntFSupfhgVLTBg==,type:str]
sops:
    kms:
    -   arn: arn:aws:kms:ap-northeast-1:123456789012:key/890hoge1-67ho-34ga-01fu-1234hoge567
        created_at: '2020-03-10T08:49:23Z'
        enc: AQICAHjzJdn8BrQ9cSoqu5NVOLqeyLNJxw4Gm2+8UkJCyqr6ngHhoC2HA0cFLSpkhEEpdOdEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMkqxdUJrTZdJglnV2AgEQgDs8jfVf1giaaMUGp0czzmgUZlAI49D3ekFiEEr9RNcWwoj55KWgNr/q+Umg3Fu+RpPd6wc32eXmw3i2Iw==
        aws_profile: ""
    gcp_kms: []
    azure_kv: []
    lastmodified: '2020-03-10T08:49:24Z'
    mac: ENC[AES256_GCM,data:Af2KHbsAqo35DyS2m4XufoqFc7x4XfNetGC1BIYcVZhy8strbhFEAn0EYn7dHXgpZJI/ZwPzmA2adhioA1+qhJIL8U/mrHJTufPJWEw/8VTkl3JoCBMWO9gB6+Ip525AwNFi6sJEj6GLbwMaI4alZsSSFGs82HiBLe0Q2OpJNQ4=,iv:VlCaQipPx9p96QB4VWl1X7UxTcDQLO1d2SVP6LMz1+g=,tag:Hkt/zqjoN60HMKR6tro60A==,type:str]
    pgp: []
    unencrypted_suffix: _unencrypted
    version: 3.5.0
```

```bash:decryption
$ sops -d enc_new_file.yml
simple: yaml_file
add: fromfile
test: encryption
```

使い方はざっとこんな感じです。

# Terraformで使ってみる
Terraformで使う場合は公式のproviderではないので自分でpluginを持ってくる必要があります。
https://github.com/carlpett/terraform-provider-sops

README.mdにも記載あるとおり[**release**](https://github.com/carlpett/terraform-provider-sops/releases)から自分の環境に合わせて持ってきます。
下記に配置してね、と記載ありますがこれだとダメな場合があるのでその場合は`.terraform/plugins/`配下に置きましょう。
>・Windows %APPDATA%\terraform.d\plugins
・All other systems ~/.terraform.d/plugins

## 書き方
非常にシンプルです。

```golang:sops.tf
provider "sops" {}

data "credentials" "new_file" {
  filename = "enc_new_file.yml"
}

resource "aws_ssm_parameter" "test" {
  name   = "sops-test"
  type   = "String"
  key_id = "alias/aws/ssm"
  value  = data.credentials.new_file.data["simple"]
}
```
プロバイダのバージョン指定は不要です。 ※ コミュニティ提供のため指定できない。
`data`構文にてクレデンシャルのファイルを指定します。あとは`data`リソースとして呼び出してあげるだけです。
これでインフラコードとクレデンシャルが一緒に管理できて幸せですね！

**2020.05.22 追記**
Terraform v0.13.0にてコミュニティプロバイダでも名前解決してくれるので苦し紛れのバイナリインストールが不要になるみたいです！
https://github.com/hashicorp/terraform/blob/master/CHANGELOG.md
>NEW FEATURES:
・Terraform now supports a decentralized namespace for providers, allowing for automatic installation of community providers from third-party namespaces in the public registry and from private registries. (More details will be added about this prior to release.)

# 所感
KMSやKey Vault側で権限を管理しているため、権限管理も簡単ですしなにより一緒に管理できるのが非常に楽でいいです！たとえYAMLファイルをお漏らししても復号できないので安心ですね。(そもそもお漏らししないのが一番ですが。。)
ぜひこれで少しでも幸せになる方が増えればと思います。

# 参考
[ファイルをAWS KMSで暗号化して安全にgit commitできるようにするmozilla/sopsの使い方](https://qiita.com/mumoshu/items/d5c8b93ed7898620930b)