【Kubernetes】SOPSとageでSecretのマニフェストを暗号化

2025.03.21
2025.03.21
Kubernetes
SecretSOPSage

本ページはAmazonアフィリエイトのリンクを含みます。

はじめに

今回は、SOPSageを使用して、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

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 sops

age

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.

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 age

SOPSとageで暗号化・復号化

簡単にSOPSとageを使って暗号化・復号化する方法を紹介します。

まず、ageで鍵を生成します。

1age-keygen -o key.txt

実行すると、下記のように公開鍵が出力されます。

1Public key: age1fhhsvxmd55dwv5sak0vulq3utk5sxqas3l899u6apzkxu54jws3qeawch7

また、生成されたkey.txtを確認すると、下記のように公開鍵と秘密鍵が記載されています。今回は試すだけなので公開してますが、実際には公開しないように注意してください(特に秘密鍵)。

1cat 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.yaml

test.yamlを確認すると、元の値に戻っていることが確認できます。

1secret: this is a secret

Secretのマニフェストを暗号化・複合化してみる

実際に、Secretのマニフェストを暗号化・複合化してみます。

Secretのマニフェストの作成

まず、Secretのマニフェスト(secret.yaml)を作成します。このまま、Gitにコミットしてしまわないようにgitignoreなどで除外しておくのがおすすめです。

secret.yaml
1apiVersion: v1
2kind: Secret
3metadata:
4  name: secret-with-sops-age
5type: Opaque
6data:
7  PASSWORD: dGVzdHBhc3N3b3Jk

SOPSとageの準備

次に、SOPSとageの準備をします。

まず、ageで鍵を生成します。この鍵はGitにコミットしないように注意してください。今回は、複合化時に鍵の保存場所を~/.config/sops/age/keys.txtにしているので、その場所に保存します。

1age-keygen >> ~/.config/sops/age/keys.txt

次に、SOPSの設定ファイル(.sops.yaml)をプロジェクトのルートディレクトリに作成して、暗号化に使用するageの公開鍵の指定と、マニフェストの余計な部分を暗号化しないように暗号化する値の指定をします。

.sops.yaml
1creation_rules:
2  - encrypted_regex: ^(PASSWORD)$
3    age: age1tpey7z3lx8dy7hcc6pl7868d4ye8fg2kjcw6ply3tcndywu33glste57nk

Secretのマニフェストを暗号化

SOPSを使ってSecretのマニフェストを暗号化します。今回は元のファイルを上書きせず、新しいファイル(secret.enc.yaml)に出力します。

1sops -e secret.yaml > secret.enc.yaml

暗号化されたファイル(secret.enc.yaml)は下記のようになります。PASSWORDの値のみが暗号化されています。

secret.enc.yaml
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のマニフェストが復元されます。

secret.yaml
1apiVersion: v1
2kind: Secret
3metadata:
4    name: secret-with-sops-age
5type: Opaque
6data:
7    PASSWORD: dGVzdHBhc3N3b3Jk

まとめ

今回は、SOPSとageを使ってKubernetesのSecretのマニフェストを暗号化する方法について紹介しました。

SOPSとageで暗号化することで、機密情報の漏洩リスクを軽減することができます。また、SOPSを使うことで、ファイル全体ではなく、特定の値だけを暗号化できるので、マニフェスト自体の可読性を保ちつつ、機密情報を保護することができます。

参考

Support

\ この記事が役に立ったと思ったら、サポートお願いします! /

buy me a coffee
Share

Profile

author

Masa

都内のIT企業で働くエンジニア
自分が学んだことをブログでわかりやすく発信していきながらスキルアップを目指していきます!

buy me a coffee