はじめに
今回は、SOPSとageを使用して、KubernetesのSecretのマニフェストを暗号化する方法について紹介します。
KubernetesのSecret管理
KubernetesのSecretは、機密情報を管理するためのリソースですが、マニフェスト内の値はBase64でエンコードされているだけなので、デコードしてしまえば簡単に中身を見ることができてしまいます。
例えば、下記のようなSecretのマニフェストがあったとしても、
1apiVersion: v1
2kind: Secret
3metadata:
4  name: example-secret
5type: Opaque
6data:
7  secret: dGhpcyBpcyBjcmVkZW50aWFs下記のようにデコードすることで中身を見ることができます。
1echo "dGhpcyBpcyBjcmVkZW50aWFs" | base64 -dなので、このままマニフェストをGitなどで管理するのはセキュリティ上問題があるため、Kubernetesでは機密情報をSecretを使わず外部のセキュアなストレージに保存するか、Vaultなどの専用のツールを使ったりすることもあります。
ですが、今回はSOPSとageを使ってSecretのマニフェストを暗号化して、Gitなどで管理できるようにする方法を紹介します。
SOPSとage
まずは、SOPSとageについて簡単に説明します。
SOPS
SOPSは、YAMLやJSONなどのファイルを暗号化・復号化するためのツールです。実際に暗号化するのは、ageやGPGなどの暗号化ツールを使い、SOPS自体が暗号化を行うわけではありません。
SOPSを使うことで、ファイル全体ではなく、特定の値だけを暗号化できるようになります。
GitHub - getsops/sops: Simple and flexible tool for managing secrets
Simple and flexible tool for managing secrets. Contribute to getsops/sops development by creating an account on GitHub.
brewを使ってインストールすることができます。
1brew install sopsage
ageは、シンプルな暗号化ツールです。Goのライブラリとしても提供されています。
GitHub - FiloSottile/age: A simple, modern and secure encryption tool (and Go library) with small explicit keys, no config options, and UNIX-style composability.
A simple, modern and secure encryption tool (and Go library) with small explicit keys, no config options, and UNIX-style composability. - FiloSottile/age
下記の書籍でも、1st EditionではGPGを使って暗号化を行っていましたが、2nd Editionではageを使って暗号化を行っています。
brewを使ってインストールすることができます。
1brew install ageSOPSとageで暗号化・復号化
簡単にSOPSとageを使って暗号化・復号化する方法を紹介します。
まず、ageで鍵を生成します。
1age-keygen -o key.txt実行すると、下記のように公開鍵が出力されます。
1Public key: age1fhhsvxmd55dwv5sak0vulq3utk5sxqas3l899u6apzkxu54jws3qeawch7また、生成されたkey.txtを確認すると、下記のように公開鍵と秘密鍵が記載されています。今回は試すだけなので公開してますが、実際には公開しないように注意してください(特に秘密鍵)。
1❯ cat key.txt
2# created: 2025-03-21T08:34:15+09:00
3# public key: age1fhhsvxmd55dwv5sak0vulq3utk5sxqas3l899u6apzkxu54jws3qeawch7
4AGE-SECRET-KEY-1RLUKSQZTFK2228Z4E3GV9658EJG9VGL6NUYXS3CE2EX362VSNGDQE6CDWQ次に、暗号化したいファイル(test.yaml)を作成します。
1secret: "this is a secret"sopsコマンドで暗号化します。-e(--encrypt)オプションを使って暗号化、-i(--in-place)オプションを使ってファイルを上書きします。また、--ageオプションでageの公開鍵を指定します。
1sops -e -i --age age1fhhsvxmd55dwv5sak0vulq3utk5sxqas3l899u6apzkxu54jws3qeawch7 test.yaml暗号化されたファイルは下記のようになります。secretの値が暗号化されています。また、sopsの情報も追加されています。
1secret: ENC[AES256_GCM,data:yCSBwHb5WJaG9W28C24KjA==,iv:D0BwUYDeJmU34Qx+uDBao7i0Ca8rRe3f1HEgC06ZMQE=,tag:D8cBjIO5NVsQvOmMz+N9SA==,type:str]
2sops:
3    kms: []
4    gcp_kms: []
5    azure_kv: []
6    hc_vault: []
7    age:
8        - recipient: age1fhhsvxmd55dwv5sak0vulq3utk5sxqas3l899u6apzkxu54jws3qeawch7
9          enc: |
10            -----BEGIN AGE ENCRYPTED FILE-----
11            YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBuU0pobytLNDI5cnk2L3lv
12            ODFUd2hCUG9TL3lKSFJ0MEZUaHZNSVNxdFZVCjhsVmpNTmxLTWpRM1F5MEhramZK
13            eHBHZ2VWV29NbjZSdHZoM0pGQk12ZW8KLS0tIGtQZXdKZ2tmTDhqbkpkY21yOTYw
14            QTFpY01EeDlzOFI1N0o1Y2hxVHJGWGcKeV8eq9zVhyRdIz2EAElhVMlC6v/K/wAB
15            GPzb7YNxhvPrWCq/LMgnP9NplFXMFZwyrPODXbrs48IwPGNNGxw8HQ==
16            -----END AGE ENCRYPTED FILE-----
17    lastmodified: "2025-03-20T23:46:09Z"
18    mac: ENC[AES256_GCM,data:5C8ZAR229it4OJ+UcfgASufYlyN8Vt5T4DnPBbiPWHZ5qiDa4rqQHZmG/s+EoFRs7ubwDKAuqrkLIk+cRyUNij/FTiOjfK0os6RWJsEaOYbWNzNJqMy45fOT5hkyRN24fCrBzcecPBpKfUZYiby6WnI3JS1d6VsebY4CO+q67+4=,iv:CGFXjjYFax8sViML6dIDryDChz7y0aGqzlu5FZPEh/s=,tag:l3BC/vhhBBGdntfg0EGMYw==,type:str]
19    pgp: []
20    unencrypted_suffix: _unencrypted
21    version: 3.9.4復号化する場合、Macだとデフォルトで$HOME/Library/Application Support/sops/age/keys.txtにある秘密鍵を使って復号しようとします。なので、作成したkey.txtの内容を移しておく必要があります。また、XDG_CONFIG_HOME環境変数を設定しておけば$XDG_CONFIG_HOME/sops/age/keys.txtを指定したり、SOPS_AGE_KEY_FILE環墋変数を使って任意のファイルを指定することもできます。
今回は、作成したkey.txtを使って、-d(--decrypt)オプションで復号化します。
1SOPS_AGE_KEY_FILE=$(pwd)/key.txt sops -d -i test.yamltest.yamlを確認すると、元の値に戻っていることが確認できます。
1secret: this is a secretSecretのマニフェストを暗号化・複合化してみる
実際に、Secretのマニフェストを暗号化・複合化してみます。
Secretのマニフェストの作成
まず、Secretのマニフェスト(secret.yaml)を作成します。このまま、Gitにコミットしてしまわないようにgitignoreなどで除外しておくのがおすすめです。
1apiVersion: v1
2kind: Secret
3metadata:
4  name: secret-with-sops-age
5type: Opaque
6data:
7  PASSWORD: dGVzdHBhc3N3b3JkSOPSとageの準備
次に、SOPSとageの準備をします。
まず、ageで鍵を生成します。この鍵はGitにコミットしないように注意してください。今回は、複合化時に鍵の保存場所を~/.config/sops/age/keys.txtにしているので、その場所に保存します。
1age-keygen >> ~/.config/sops/age/keys.txt次に、SOPSの設定ファイル(.sops.yaml)をプロジェクトのルートディレクトリに作成して、暗号化に使用するageの公開鍵の指定と、マニフェストの余計な部分を暗号化しないように暗号化する値の指定をします。
1creation_rules:
2  - encrypted_regex: ^(PASSWORD)$
3    age: age1tpey7z3lx8dy7hcc6pl7868d4ye8fg2kjcw6ply3tcndywu33glste57nkSecretのマニフェストを暗号化
SOPSを使ってSecretのマニフェストを暗号化します。今回は元のファイルを上書きせず、新しいファイル(secret.enc.yaml)に出力します。
1sops -e secret.yaml > secret.enc.yaml暗号化されたファイル(secret.enc.yaml)は下記のようになります。PASSWORDの値のみが暗号化されています。
1apiVersion: v1
2kind: Secret
3metadata:
4    name: secret-with-sops-age
5type: Opaque
6data:
7    PASSWORD: ENC[AES256_GCM,data:D2M29p8UyUGWR4pYXebOSw==,iv:1DYb9+4x+YVDn5oUFjAlXlBiJqTPiE9b+tQUC+reauI=,tag:iyODzlElddtOo5xroBq5mA==,type:str]
8sops:
9    kms: []
10    gcp_kms: []
11    azure_kv: []
12    hc_vault: []
13    age:
14        - recipient: age1tpey7z3lx8dy7hcc6pl7868d4ye8fg2kjcw6ply3tcndywu33glste57nk
15          enc: |
16            -----BEGIN AGE ENCRYPTED FILE-----
17            YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB5ZmM1Y3Vpd0RvWGhGdUda
18            c3pndEpqV1BTYnBaWnFsWWxtakkwa3dLdmtjClpNeXVvR1VsZ0N6WWpNRXBPRmJO
19            UnYyMXMvWXlQRTNDV0JLdGFzQUlZNVkKLS0tIEhJalBuUkFBd2lzTUJ5WkVaa0cz
20            ajh2MEdFNjdXYVhHU0IxbDhOa3ZmMVkKCiK1B3yKXjWeAhYtNfh3QjZtMQuW96NQ
21            wirazxlu6E+O2GVCoU6/TtQj4GxUuqdacvM7E4j4GJpILQ2E+Y2k7A==
22            -----END AGE ENCRYPTED FILE-----
23    lastmodified: "2025-03-21T00:31:52Z"
24    mac: ENC[AES256_GCM,data:6iJ0XwpzmcAKlMMf2JPKXqBH1E8y5diX2LNlMnW8A03bglvdanjSSkTLQ5nuaKmb5JzBChq4i0u0nhSTmCFc0iYqL20GAMhB781vB0OjbJfepWP+U07ItBYkscksmMHPQ8F0Vjc3+7Ng+H9eCPCZhYcDL976qvAtUSFi/e7ZTH4=,iv:+6X8gei2JNbjftKSc4z98opVrqbT0RfJ5qY+E1Bj8uE=,tag:rTg82kKA/cu/irPLAbRLTg==,type:str]
25    pgp: []
26    encrypted_regex: ^(PASSWORD)$
27    version: 3.9.4これで、GitにコミットしてもSecretのマニフェストが暗号化されているので、安心して管理することができます。
Secretのマニフェストを復号化
Secretのマニフェストを復号化する場合は、下記のコマンドを実行します。
1sops -d secret.enc.yaml > secret.yamlこれで元のSecretのマニフェストが復元されます。
1apiVersion: v1
2kind: Secret
3metadata:
4    name: secret-with-sops-age
5type: Opaque
6data:
7    PASSWORD: dGVzdHBhc3N3b3Jkまとめ
今回は、SOPSとageを使ってKubernetesのSecretのマニフェストを暗号化する方法について紹介しました。
SOPSとageで暗号化することで、機密情報の漏洩リスクを軽減することができます。また、SOPSを使うことで、ファイル全体ではなく、特定の値だけを暗号化できるので、マニフェスト自体の可読性を保ちつつ、機密情報を保護することができます。
参考
- getsops/sops: Simple and flexible tool for managing secrets
 - FiloSottile/age: A simple, modern and secure encryption tool (and Go library) with small explicit keys, no config options, and UNIX-style composability.
 





