SealedSecretを使ってk8sのSecretを暗号化する

k8sのSecretを暗号化してgitにcommitできるようにするため、SealedSecretを使ってみる

SealedSecret Controlerを導入

SealedSecretが動くためのcontrollerを導入する必要がある
https://github.com/bitnami-labs/sealed-secrets?tab=readme-ov-file#controller
KustomizeとHelm Chartを使うやりかたが案内されている

Helmを使って導入する

helm repo add sealed-secrets https://bitnami-labs.github.io/sealed-secrets
helm install sealed-secrets -n kube-system --set-string fullnameOverride=sealed-secrets-controller sealed-secrets/sealed-secrets

kubeseal をインストール

SealedSecret Controllerはクラスタ側のリソースであるのに対し、クライアントとしてkubesealというものをインストールする

https://github.com/bitnami-labs/sealed-secrets?tab=readme-ov-file#kubeseal
homebrew, macports, nixpkgs, from source が案内されているが、asdf-vm でもpluginが提供されていたのでasdfでインストールした

asdf plugin add kubeseal
asdf install kubeseal latest

平文Secretを暗号化(SealedSecret化)してみる

まずは平文でSecretを作る

# secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: mysecret
type: Opaque
stringData:
  username: getwild

暗号化する

kubeseal --format=yaml < secret.yaml > sealed-secret.yaml

暗号化されてこんな感じのyamlが作られる

# sealed-secret.yaml
---
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
  creationTimestamp: null
  name: mysecret
  namespace: default
spec:
  encryptedData:
    username: AgAqQuQolTbXmYHTiQiz1wIY3M3T3v00AOjA5ae5+Szh6aNWdZ069mNxhRGY8fUDnI+rypiSfbdjfPBybOuuhQR3CNlJtvBYKs3gkFb1XeYujK/k2QeF5mxM5qFx1GzxsCoiFCdMM/G3SLGquldMOMavsie19sqot/Cpkh449aDq7Q+KA5X2O+weWh2Y70AkpyX+AirrCWAKB7qX/nRW4UeNv6N0d6s+4cscKc+CVrLQptzFzZOMY/ztKysctXe2UK/n0esoH4xFbPTfVxacLotoYl/rpnKZ6WcU3NrVtPpsuRSVSbFyEArBOH8UlV5kkkVXQs8vq7Twr+ShYzZfR09xw6FkVXSXB91JCCx+vJ6FoCoP+5ljlHNv2o0BR/xO3X0prDKIoUQhJbc/PDph705X2pMFAeJB1GmKct/xMEyrSylkncZVJywsgTUO/nYmsjnGA6VYlwBHQdFkzeoo8rH93Gki+ihbnMFMCazh07ZKbqvoQwCqG7OXpclIJU9GgrAUc2RsIerL3+6q3Fhlz18mtutw+04Huv+CqKCwo9xjBJNo0jFt151yb7CXm9Td5uwrhMKC13c4WUzDuQDcjmsfVJaoGZiiAqkfeQ6fRKLgBn0ZVKzHsEmIyIn7lRSY2kiQyQi3QMEZ0Rgv8SlHE5kTuglEvf1E1yKCoAdvIFuwFk4BxknvV+wkB/JebC5aUnJqUwWPGxbm
  template:
    metadata:
      creationTimestamp: null
      name: mysecret
      namespace: default
    type: Opaque

SealedSecretをapplyする

kubectl apply -f sealed-secret.yaml

以下のように作られる

$ kubectl get sealedsecret
NAME                       STATUS   SYNCED   AGE
mysecret                            True     45m

$ kubectl get secret
NAME                       TYPE     DATA   AGE
mysecret                   Opaque   1      46m

Secretを更新する

https://github.com/bitnami-labs/sealed-secrets/tree/main/docs/examples/config-template

echo -n andtough \
| kubectl create secret generic mysecret --dry-run=client --from-file=username=/dev/stdin -o json \
| kubeseal -o yaml --merge-into sealed-secret.yml

ローカルでSealedSecretを復号する

https://github.com/bitnami-labs/sealed-secrets?tab=readme-ov-file#can-i-decrypt-my-secrets-offline-with-a-backup-key

秘密鍵を取得

kubectl get secret -n kube-system -l sealedsecrets.bitnami.com/sealed-secrets-key -o json | jq -r '.items[].data."tls.key"' | base64 -d > key.pem

ローカルで秘密鍵を使って復号
secretの値はbase64で入っている

cat sealed-secret.yml| kubeseal --recovery-unseal --recovery-private-key key.pem
{
  "kind": "Secret",
  "apiVersion": "v1",
  "metadata": {
    "name": "mysecret",
    "namespace": "default",
    "creationTimestamp": null,
    "ownerReferences": [
      {
        "apiVersion": "bitnami.com/v1alpha1",
        "kind": "SealedSecret",
        "name": "mysecret",
        "uid": "",
        "controller": true
      }
    ]
  },
  "data": {
    "username": "Z2V0d2lsZA=="
  },
  "type": "Opaque"
}