🔒

KubernetesにBitwarden Secrets Managerを導入してみる

に公開

自宅サーバーでk8sを構築しているのですが、Secretの管理に頭を悩ませていました。
kubectlで管理するのは面倒くさいし、自宅サーバーなのでロストする可能性もあります。
これを改善しようと調べてみると、いくつかの選択肢がありました。

  1. PortainerLens でSecretのGUI管理
    → 自宅k8sで、オペレーションミスでSecretを失う可能性もあるため却下

  2. Sealed Secretssops といった暗号化済みのテキストを書き込み、使用時に復号する方式
    → 暗号化されているとはいえGit履歴に残るのが嫌

  3. Bitwarden Secrets Manager(BSM)External Secrets Operator(ESO) で管理
    → 普段からBitwardenを使用していたことと、外部のサービスに預けられるのでデータを失う確率が自分で管理するより低いだろう

パッとこの3つが上がったのですが、3を選択しました。
調べてもBSMの情報はあまりなかったので記事にしてみることにしました。
ちなみに Bitwarden Passowrd ManagerBitwarden Secrets Manager は全くの別物なので注意してください。
Password Managerの方は1Passowrdみたいなよくあるパスワードマネージャーで、Secrets ManagerはAWS Secrets Mangerのようなシステム環境向けのシークレット管理サービスです。

導入

External Secrets Operator (ESO) のインストール

まずはHelmでExternal Secrets Operatorをインストールします。
BSMを使用する場合、Bitwarden SDK Serverも一緒にインストールする必要があります。

https://external-secrets.io/latest/provider/bitwarden-secrets-manager

# Helmリポジトリの追加
helm repo add external-secrets https://charts.external-secrets.io

# External Secrets OperatorとBitwarden SDK Serverをインストール
helm install external-secrets \
  external-secrets/external-secrets \
  -n external-secrets \
  --create-namespace \
  --set bitwarden-sdk-server.enabled=true

Bitwarden SDK ServerはHTTPSで動作するので、cert-managerで証明書を生成する必要があります。
cert-managerがまだインストールされていない場合は、先にインストールしてください。

Bitwarden Secrets Managerの準備

BSMにアクセスするためには、Machine Accountが必要です。
BitwardenのWebコンソールからMachine Accountを作成し、アクセストークンを取得してください。

取得したトークンをKubernetes Secretとして保存します。

kubectl create secret generic bitwarden-access-token \
  -n default \
  --from-literal=token='YOUR_ACCESS_TOKEN_HERE'

SecretStore の設定

SecretStoreを作成して、ESOがBSMに接続できるようにします。

apiVersion: external-secrets.io/v1
kind: SecretStore
metadata:
  name: bitwarden-secretsmanager
spec:
  provider:
    bitwardensecretsmanager:
      apiURL: https://api.bitwarden.com
      identityURL: https://identity.bitwarden.com
      auth:
        secretRef:
          credentials:
            key: token
            name: bitwarden-access-token
      bitwardenServerSDKURL: https://bitwarden-sdk-server.external-secrets.svc.cluster.local:9998
      # cert-managerで生成した証明書のCA Bundleを設定
      caBundle: "<BASE64_ENCODED_CA_CERTIFICATE>"
      # BSMのOrganization ID
      organizationID: "your-organization-id"
      # BSMのProject ID
      projectID: "your-project-id"

ExternalSecret の設定

SecretStoreの準備ができたら、ExternalSecretを作成してBSMからシークレットを取得します。

UUIDで取得する場合

apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
  name: my-external-secret
spec:
  refreshInterval: 1h
  secretStoreRef:
    name: bitwarden-secretsmanager
    kind: SecretStore
  target:
    name: my-k8s-secret
    creationPolicy: Owner
  data:
    - secretKey: my-secret-key
      remoteRef:
        key: "339062b8-a5a1-4303-bf1d-b1920146a622"  # BSMのシークレットUUID

名前で取得する場合

apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
  name: my-external-secret
spec:
  refreshInterval: 1h
  secretStoreRef:
    name: bitwarden-secretsmanager
    kind: SecretStore
  target:
    name: my-k8s-secret
    creationPolicy: Owner
  data:
    - secretKey: my-secret-key
      remoteRef:
        key: "secret-name"  # BSMで設定したシークレット名

動作確認

ExternalSecretが正しく同期されているか確認します。

kubectl get externalsecret my-external-secret

# 出力例
# NAME                 STORE                     REFRESH INTERVAL   STATUS         READY
# my-external-secret   bitwarden-secretsmanager  1h                 SecretSynced   True

StatusがSecretSyncedになっていれば成功です。
作成されたSecretの内容も確認できます。

kubectl get secret my-k8s-secret -o jsonpath='{.data.my-secret-key}' | base64 -d
GitHubで編集を提案

Discussion