このページの本文へ

FIXER cloud.config Tech Blog

「SealedSecrets」を使ってKubernetesのSecretをGitで管理する

2022年06月10日 10時00分更新

文● 毛利 真士/FIXER

  • この記事をはてなブックマークに追加
  • 本文印刷

 本記事はFIXERが提供する「cloud.config Tech Blog」に掲載された「SealedSecretsを使ってKubernetesのSecretをGit管理する #Kubernetesリレー」を再編集したものです。

 こんにちは、毛利です。最近趣味サーバをKubernetesに移行して遊んでいます。最近の気づきとしては、Kubernetesの仕組みレベルの視点と、Kubernetesを使う側の視点でそこそこギャップがあるなぁと思いました。今回はSecretを暗号化できるSealedSecretsの話をします。

背景と概要

 KubernetesのSecretをGit管理できたらと思ったことはないでしょうか? Git管理することで、以下のようなメリットがありそうです。

1. GitHub等のPull Requestやレビューのフローに乗せられる
2. ファイル管理をする場所をGitに統一でき、管理場所がばらけない
3. バージョン管理ができ、履歴をたどれる

 しかし、SecretをGitにそのまま放り込むのはセキュリティーの観点からよくないです。

 そこで、SealedSecretsの出番です。SealedSecretsでは、Kubernetes環境が持っている秘密鍵でのみSecretを復号して見れるように、Secretを暗号化します。これによって、秘密鍵を持っていないとSecretの元の文字列がわからない仕組みが実現されます。この仕組みはGitOpsでよく使われているようです。

手順

 確認した環境はWindows(PowerShell)とArch Linuxです。また、Kubernetesの操作用にLensを使っています。Lensは使いやすくて見た目がかっこいいのでおすすめです。

1. kubesealコマンドを準備

 まず、Secretの暗号化など、SealedSecretsに関する作業を手元で行なうためのkubesealコマンドを準備します。

 Windowsの場合はReleases · bitnami-labs/sealed-secrets(github.com)からダウンロードしてパスを通すとOKです。

 Arch Linuxの場合はpacmanで入ります。


pacman -S kubeseal


2. Helmを使ってSealedSecretsの準備

 次にKubernetes側にSealedSecretsの準備をします。

 以下のコマンドを実行してSealedSecretsをinstallできるようにします。 環境によってはhelm3ではなくhelmの場合もあるかと思います。適宜読み替えてください。


helm3 repo add sealed-secrets https://bitnami-labs.github.io/sealed-secrets


 インストール(デプロイ)のコマンドは次の通りです。このコマンドを実行したときに使い方の説明が出ます。メモしておくことをおすすめします。


helm3 install <リリース名> sealed-secrets/sealed-secrets -n </namespace名>


 例えば、次のようなコマンドを実行します。


helm3 install my-release sealed-secrets/sealed-secrets -n default

3. 公開鍵の取得

 デプロイしたSealedSecretsの公開鍵を取得します。

 公式の手順では、リダイレクトを使って公開鍵のファイルを作成していますが、リダイレクトではなく-wオプションを使うことをおすすめします。PowerShellでリダイレクトを使った場合、暗号化したSecretを作成する際にerror: data does not contain any valid RSA or ECDSA certificatesとエラーが出ることがあります(おそらく文字コードの関係だと思います)。この問題は手元では-wオプションを使うことで回避できました。

 公開鍵を取得するコマンドは以下の通りです。


kubeseal --controller-name=<sealedsecretsのdeployment名> --controller-namespace=<namespace名> --fetch-cert -w <公開鍵の出力先ファイルのパス>

 例えば、次のようなコマンドを実行します。


kubeseal --controller-name=my-release-sealed-secrets --controller-namespace=default --fetch-cert -w mycert.pem

4. 暗号化したSecretのyamlを作成

 以下のコマンドで実行できます。--from-literalは複数指定できます。


kubectl create secret generic <secret名> --dry-run=client --from-literal=<key>=<value> -n <namespace名> -o json | kubeseal --controller-name=<sealedsecretsのdeployment名> --controller-namespace=<namespace名> --cert <公開鍵ファイルのパス> -w <暗号化されたSecretの出力再ファイルのパス>


 例えば、次のようなコマンドを実行します。


kubectl create secret generic testsecret-20220524 --dry-run=client --from-literal=TOKEN=token -n default -o json | kubeseal --controller-name=my-release-sealed-secrets --controller-namespace=default --cert mycert.pem -w testsecret-20220524-sealed.yaml


 上記のコマンドを実行すると、以下のようなファイルが生成されます。Secretの値がシンプルなbase64ではなく、長い文字列になっていることが確認できます。 Secretの値が暗号化されているので、SecretをそのままGitで管理するよりも安全に管理できます。


apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
  creationTimestamp: null
  name: testsecret-20220524
  namespace: default
spec:
  encryptedData:
    TOKEN: <暗号化された文字列>
  template:
    data: null
    metadata:
      creationTimestamp: null
      name: testsecret-20220524
      namespace: default


 もしSecretのyamlファイルから作る場合は -f オプションを使って暗号化できます。できますが、間違って暗号化前のSecretをコミットしてしまう可能性があるのであんまりおすすめしません。


kubeseal --format=yaml --cert=<公開鍵ファイルのパス> -f <暗号化前のSecretファイルのパス> -w <暗号化されたSecretの出力先ファイルのパス>

5. 暗号化されたSecretの適用

 暗号化されたSecretの適用は以下のコマンドでできます。上書きしても良い場合はkubectl applyでもできますが、いざとなったときに戻すことを考えると、更新する際にはSecretの名前を変えて新規で登録することをおすすめします。


kubectl create -f <暗号化後のSecretファイル>


 例えば、次のコマンドを実行します。


kubectl create -f testsecret-20220524-sealed.yaml


 適用すると、Kubernetes上でSealedSecretsによって復号され、復号されたSecretが登録されます。

 復号されたSecretの確認は、以下のコマンドでできます。


kubectl get secret <secret名> -o yaml


 例えば、次のような実行結果になり、復号されてSecretが登録されていることが分かります。


$ kubectl get secret testsecret-20220524 -o yaml
apiVersion: v1
data:
  TOKEN: dG9rZW4=
kind: Secret
metadata:
  creationTimestamp: "2022-05-24T08:54:28Z"
  name: testsecret-20220524
  namespace: default
  ownerReferences:
  - apiVersion: bitnami.com/v1alpha1
    controller: true
    kind: SealedSecret
    name: testsecret-20220524
    uid: 649e23ee-aa7d-42b3-b519-7240c59f98fe
  resourceVersion: "180816"
  uid: c8ae473c-0b4a-4df9-a66c-c491c1fb1434
type: Opaque


 あとはDeploymentなどからいつもの手順でSecretを参照できます。めでたしめでたし。

おわりに

 GitOps、秘密情報の管理どうするんだよと思っていたけどなるほどなぁとなった。動いているシステムとリポジトリ間の相互に(ゆるく)依存関係があるのちょっと不思議な感じ。リポジトリはシステムの一部なのかもね。

参考

・SealedSecretsのリポジトリ

毛利 真士/FIXER

三重県出身の毛利真士です
趣味は競プロ、Rust、サーバ周り、自作言語・コンパイラなどなどです

カテゴリートップへ