Securely manage .env containing sensitive information in VSCode: SOPS

2023年6月4回目です。

「積読」ならぬ、「積Issue」を減らす個人的なメモです。

Local の `.env` に password などの機密情報を残した経験はありますか？
それを commit してしまい、履歴から消した経験はありますか？？

ぼく自身経験があります。
また、同僚のcommitで見かけることがあります。

developer が安全に開発に集中できる環境を提供するため、統一した対策を developer に提供する必要があります。

具体的には、[SOPS:Secrets OPerationS](https://github.com/mozilla/sops) について調べます。

https://github.com/mozilla/sops

今回使用した Code は、こちらです。

https://github.com/danny-yamamoto/go-ent-example

## Installation
### SOPS
- dev container の Dockerfile に設定しています。

https://github.com/danny-yamamoto/go-ent-example/blob/71cc5109aec1194b87f74d65795e69b7d0701679/.devcontainer/Dockerfile#L20-L27

### age
- 暗号化ツールです。
- 依存なしに構成するため、age を使います。
- Cloud KMS なども使えます。`--gcp-kms [value] `
- dev container の Dockerfile に設定しています。

https://github.com/danny-yamamoto/go-ent-example/blob/71cc5109aec1194b87f74d65795e69b7d0701679/.devcontainer/Dockerfile#L30C1-L30C1

```bash
# key を作成します。
age-keygen -o keys.txt
mkdir -p $XDG_CONFIG_HOME/sops/age
mv keys.txt $XDG_CONFIG_HOME/sops/age/.
```

## Let's encrypt
### 暗号化前
```bash
root ➜ /workspaces/go-ent-example (main) $ cat sample.json 
{
        "hello": "Welcome to SOPS! Edit this file as you please!",
        "example_key": "example_value",
        "example_array": ["example_value1", "example_value2"],
        "example_number": 1234.56789,
        "example_booleans": [true, false]
}
root ➜ /workspaces/go-ent-example (main) $ 
```
### 暗号化
```bash
root ➜ /workspaces/go-ent-example (main) $ sops -e --age age1d2ku3ya3xa5ravmzvjvtl7sr40zyxfu4xrsp0g60xhje9wgr83dqqy7xra sample.json > enc.json
root ➜ /workspaces/go-ent-example (main) $ cat enc.json 
{
        "hello": "ENC[AES256_GCM,data:K6CADCb1t7V7wdCEPb20ZI6ixETDLvPaNW6diwhZ+HeeEZzNO0/0k0R7PGuQCA==,iv:CYtyN1j6mw0hjx5ei7oUHvpGBlGncUWhpG4FXdszJq0=,tag:/IA3CwMI/G+9XuTIHvVdog==,type:str]",
        "example_key": "ENC[AES256_GCM,data:b5IQPpp7N3D/fMVkPg==,iv:0cAhm5MTKIuQrVBVsPVoGfll01VFVBeLXHbt2hU39Ho=,tag:DlhZemgREki84DMmBXAiCA==,type:str]",
        "example_array": [
                "ENC[AES256_GCM,data:wo81LwGKjpJCniLIHFE=,iv:/AxPLhEEx4uX5/nTl3YRPWkvyg8PuEbldskE2J39MNw=,tag:oE0s8FcCQqRyGnc3LGZHOA==,type:str]",
                "ENC[AES256_GCM,data:4vEug2JFtJUJ97ZK/WA=,iv:wt4dNuYds5lEDPqx6nQew3KF+wcHQOTblUyzFZu06iE=,tag:DQokgrNGkS00oDx27LfFVA==,type:str]"
        ],
        "example_number": "ENC[AES256_GCM,data:OdOVRGuGYH4f3Q==,iv:P30Fo1W218zbytUsyFMAA6Enw3SLN9KVQBEfLeuHUws=,tag:EwxB63OS6nSl4I3b00biRQ==,type:float]",
        "example_booleans": [
                "ENC[AES256_GCM,data:KZEzDQ==,iv:uQn7bADQp1taReLL0VHdkFzx56HzTbH8sF+hQuRv+DE=,tag:f+y/Xs21Q3f5cdiBS3La4A==,type:bool]",
                "ENC[AES256_GCM,data:3HUKvnk=,iv:86CNbdkew83PSkyu/hBudTKz3mOazo7gxEgYsTSOEFE=,tag:7aq3/qR+YFTKHtA4eDVJDA==,type:bool]"
        ],
        "sops": {
                "kms": null,
                "gcp_kms": null,
                "azure_kv": null,
                "hc_vault": null,
                "age": [
                        {
                                "recipient": "age1d2ku3ya3xa5ravmzvjvtl7sr40zyxfu4xrsp0g60xhje9wgr83dqqy7xra",
                                "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBRV0VLQitkQy9Qd3grSzdj\nME5ZUjJETnFuWEdYRXZteFRWUGNXOEwvQVFvCjVXSE13b2ZCdnNWYzVaL1FUU2th\nRGhPVHh5bkU1djJoWWFpSFBsVlFHcncKLS0tIGZBWndoSmg2QXZUQUQvYkVWNkhl\nNGM0MWt6RndWSWRyYytBZjQ0WFlJTFUKWfJcEL50NQu6zObN/euA/wCuuy2q/FcB\nhL1n/QeD0CWHTD5JQjzIxUjj/pEx87Bwr+UQlN9/RSMW+oT3Bts4+w==\n-----END AGE ENCRYPTED FILE-----\n"
                        }
                ],
                "lastmodified": "2023-06-28T01:07:35Z",
                "mac": "ENC[AES256_GCM,data:T3Qz+zSyz9V5e+hRiNy4pMr4n7vw7GdgncnNY2iToWPxF38Cnlx1/KaKybXWEH5U2idkSZnaN8eH2BKApbB+92Gd/oLJ3iLM+hkZYK5S+2FsfzTV5fNYVdQsqC/ZHtz6sgHZrD3tNHw6BxlSbF6lI5VTMIL2AKAxX0Gd9MmWSgA=,iv:ZhQFkNRjujmeIJX8Rg0AQKJSNaJ+YA+IWcXfXe44eUQ=,tag:3rCZTIEPO0e4WLSQbc3/cQ==,type:str]",
                "pgp": null,
                "unencrypted_suffix": "_unencrypted",
                "version": "3.7.3"
        }
}
```
### 復号
```bash
root ➜ /workspaces/go-ent-example (main) $ sops -d -i enc.json
root ➜ /workspaces/go-ent-example (main) $ cat enc.json 
{
        "hello": "Welcome to SOPS! Edit this file as you please!",
        "example_key": "example_value",
        "example_array": [
                "example_value1",
                "example_value2"
        ],
        "example_number": 1234.56789,
        "example_booleans": [
                true,
                false
        ]
}root ➜ /workspaces/go-ent-example (main) $ 
```

## Summary
SOPS について書きました。

「Git に credentials が commit されてるから、履歴を消して 😠 ！」というのは最もです。

とはいえ、その credentials は rotation してしまえば良いです。

権限も minimum にしておけば事故は防げます。

そして、credentials の利用を可観測な状態にしておけば、大抵のことは問題無いと思います。

「あなたたち literacy ないよね 😤」と否定するのは、開発者の「自己効力感」を無くすことに繋がりかねないと思います。

そこは、「セキュアベース リーダーシップ」が必要だと思いますし、「自己効力感」を育てる声かけが必要だと思います。

## Reference
- [gcloud CLI をインストールする](https://cloud.google.com/sdk/docs/install?hl=ja#deb)