GitOps によるシークレット配信(ArgoCD + Vault)
シークレットマネージャー統合 では一般的なパターン、すなわち External Secrets Operator (ESO) を通じて、すでに運用しているシークレットマネージャーから DuoKey がシークレットを取得する方法を説明しています。このページは、多くのエンタープライズの プラットフォームチームがすでに標準採用している特定の組み合わせ、すなわち GitOps コントローラー としての ArgoCD と、シークレットストアとしての HashiCorp Vault(または OpenBao。 後述の OpenBao と Vault を参照)について、そのパターンを詳細な手順として 示したものです。
Git が保持するのはポインターであり、値ではありません。 ArgoCD の役割は、Git リポジトリ内の 宣言的なマニフェスト をクラスターへ反映させることです。これらのマニフェストが記述するのは、 シークレットが どこ にあり、誰 が読み取れるかということだけです。実際のシークレットの バイト列(データベースのパスワード、署名鍵)は、Git、CI パイプライン、ArgoCD の差分を通過する ことは決してありません。それらは実行時に ESO を仲介として、Vault から Pod へ直接流れます。
何がどこに置かれるか
| Git に置かれるもの(ArgoCD 管理) | Vault にのみ置かれるもの |
|---|---|
ESO のリーダー ID のための ServiceAccount | 実際のシークレットの値(DB のパスワード、署名/暗号化鍵、クライアントシークレット) |
SecretStore / ClusterSecretStore(Vault のアドレスと認証ロールを指し示します) | — |
ExternalSecret(どの Vault のパス/キーを どの Kubernetes Secret のキーにマッピングするかを宣言します) | — |
| 上記をスコープする RBAC / NetworkPolicy | — |
マニフェストにはシークレットのマテリアルが含まれないため、通常の Git プルリクエストの プロセスを通じて、他の GitOps 管理ワークロードとまったく同じように、安全にレビュー、差分確認、 監査ができます。
配信フロー
ArgoCD は SecretStore / ExternalSecret のマニフェスト(および ESO コントローラー自体)を Git から OpenShift へ同期します。次に ESO は Kubernetes の ServiceAccount トークンを用いて Vault に直接認証し、ExternalSecret が宣言した値だけを取得して、ネイティブでメモリ上の Kubernetes Secret として実体化します。DuoKey の Pod はその Secret を他と同じように利用するだけで、Vault、ArgoCD、Git のいずれとも通信しません。
- プラットフォームチームが
SecretStore/ExternalSecretのマニフェスト(同じ方法で管理する 場合は ESO の Helm リリース自体も)を GitOps リポジトリにコミットします。 - ArgoCD が変更を検知し、クラスターに適用します。他のすべてのワークロードで既に使用して いるのと同じリコンサイルループです。
- ESO は専用の名前空間内でコントローラーとして稼働し、Kubernetes 認証方式を用いて
Vault に認証します。すなわち、
SecretStoreに指定された投影済み ServiceAccount トークンを提示し、Vault がそれを OpenShift API に対して検証したうえで、構成済みのポリシーに スコープされた短命の Vault トークンを発行します。 ExternalSecretのrefreshIntervalに従って、ESO は宣言されたパスを読み取り、ネイティブな KubernetesSecretを書き込み(または更新)します。- DuoKey の Pod は通常の
envFromを通じてそのSecretを利用します。Vault、ArgoCD、Git の 存在を Pod が意識することはありません。
サイドカーパターン(変更用 Webhook がアプリケーション Pod に init コンテナとサイドカーを 注入する方式)は、シークレットをファイルとして出力し、それを環境変数として読み込むために イメージ内のシェルを前提とします。DuoKey のコンテナイメージは、シェルもパッケージ マネージャーも持たない 固定の非 root ユーザーで動作するため、その橋渡しは存在しません。 さらに、OpenShift の restricted SCC は注入されたコンテナに追加の制約を課します(任意の UID、 特権モードは既定で無効)。上記のコントローラー/プル型のパターンは DuoKey の Pod 内に何も 必要としないため、これらの最小構成イメージ上でもそのまま機能します。
Vault 側のセットアップ
Vault の管理者は、クラスターごとに一度 Kubernetes 認証方式を有効化し、DuoKey が必要とする パスのみに、それ以上広げることなくポリシーをスコープします。
vault auth enable kubernetes
vault write auth/kubernetes/config \
kubernetes_host="https://kubernetes.default.svc:443"
vault policy write duokey-read - <<'EOF'
path "secret/data/duokey/*" {
capabilities = ["read"]
}
EOF
vault write auth/kubernetes/role/duokey \
bound_service_account_names=duokey \
bound_service_account_namespaces=duokey \
policies=duokey-read \
ttl=1h
ESO 自体のために、Vault のトークンや root 資格情報が Kubernetes Secret として保存される
ことは一切ありません。信頼の基点は ServiceAccount の投影済みトークンであり、これは
OpenShift がすでに自動的にローテーションしています。
OpenShift のマニフェスト(ArgoCD 管理)
これらは GitOps リポジトリが保持するオブジェクトです。ArgoCD は他の Application と まったく同じようにこれらを適用します。
ClusterSecretStore
apiVersion: external-secrets.io/v1
kind: ClusterSecretStore
metadata:
name: vault-backend
spec:
provider:
vault:
server: "https://vault.corp.example.local:8200"
path: "secret"
version: "v2"
auth:
kubernetes:
mountPath: "kubernetes"
role: "duokey"
serviceAccountRef:
name: duokey
namespace: duokey
ExternalSecret
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: duokey-bootstrap-secrets
namespace: duokey
spec:
refreshInterval: 1h
secretStoreRef:
name: vault-backend
kind: ClusterSecretStore
target:
name: duokey-bootstrap-secrets
data:
- secretKey: DATABASE_URL
remoteRef:
key: duokey/database
property: url
- secretKey: JWT_SECRET
remoteRef:
key: duokey/signing
property: jwt_secret
- secretKey: ENCRYPTION_KEY
remoteRef:
key: duokey/signing
property: encryption_key
- secretKey: HMAC_KEY
remoteRef:
key: duokey/signing
property: hmac_key
続いて DuoKey の Deployment が envFrom を介して duokey-bootstrap-secrets を参照します。
そこに含められる変数の一覧については
Cockpit の構成 を参照してください。
このページで扱うのは、DuoKey 自身の プラットフォームのブートストラップシークレット (データベース DSN、署名/暗号化鍵)であり、Pod の起動時に一度だけ配信される、小さく厳密に スコープされた Vault のパスです。これは テナントが構成するシークレットマネージャー (テナント自身の Vault/HSM 資格情報。KMS 統合のために DuoKey Cockpit コンソール内から入力 します)とは別の関心事です。後者のデータ経路は シークレットマネージャー統合 で一般論として説明されており、 この ArgoCD 管理のフローを通過することは決してありません。
上記の ESO パターンの代わりに、DuoKey がプロセス起動時にブートストラップ用の AppRole 資格情報を 使って自ら Vault/OpenBao に接続するように構成することもできます。どちらのパターンも フェイルクローズであり、完全にサポートされています。両者を比較してプラットフォームチームの 方針に合う方を選択するには、 Cockpit の構成 → シークレットの取得元 を参照してください。
OpenShift 固有の注意事項
- SCC — ESO 自身の Pod は、デフォルトの
restricted/restricted-v2SCC の下で問題なく 動作します(特権モードもホストアクセスも不要です)。その ServiceAccount がクラスターの デフォルト SCC を使用できるようにする以上のことは必要ありません。 - Webhook の証明書 — ESO のアドミッション Webhook には TLS 証明書が必要です。ESO 組み込みの
cert-controller に管理させる(デフォルト)か、クラスターですでに
cert-managerを稼働させて いる場合はそちらに接続してください。 - etcd への露出 — 実体化された
Secretはネイティブな Kubernetes オブジェクトであり、他のSecretと同様にetcdに保存されます。クラスターで etcd 暗号化をすでに有効にしていれば、 それで対応できます。「決して etcd に触れさせない」といったより厳格なポリシーの場合は、 代わりに HashiCorp Vault CSI プロバイダーとともに Secrets Store CSI Driver を使用して ください。これは値を Pod のtmpfsにのみマウントし、ネイティブなSecretオブジェクトを 完全に省略します。この構成の適用範囲については DuoKey 担当者にご相談ください。 - ネットワーク — Vault は、ESO が稼働する名前空間から到達可能である必要があります
(
ClusterIPService とNetworkPolicyの許可ルール、あるいは Vault がクラスター外にある 場合はRoute)。サイドカーが存在しないためlocalhostによる近道もありません。コントローラーは Vault に直接接続するため、この経路には他のクラスター内 HTTP クライアントと同じ TLS および ネットワークのハードニングが必要です。 ネットワークセキュリティ を参照してください。
OpenBao と Vault
セットアップは同一です。OpenBao は Vault の API と互換性があるため、ESO の Vault プロバイダーは
OpenBao に対してもそのまま機能します。変更が必要なのは、OpenBao のアドレスを指す
spec.provider.vault.server だけです。ESO に OpenBao 専用のプロバイダーは存在せず、同じ
vault プロバイダーブロックを OpenBao のエンドポイントに向けることが、標準的でサポートされた
利用方法です。
ローテーションと監査
- Vault の
duokeyロールの TTL と、その基となるポリシーは、通常のシークレットローテーションの 周期でローテーションしてください。ESO は取得のたびに再認証するため、絞り込んだポリシーは次のrefreshIntervalで有効になり、認可 の変更のために Pod を再起動する必要はありません (ローテーションされたシークレットの 値 を反映するには、環境変数の変更をアプリケーションが どう扱うかに依存します。DuoKey 自身の挙動については Cockpit の構成 を参照してください)。 - Vault からの読み取りはすべて Vault 自身の監査デバイスによって記録されます。まだ有効にして いない場合は有効にしてください。これは、ESO が何をいつ取得したかを示す信頼できる記録であり、 DuoKey 自身の 監査証跡 とは独立しています。
duokey-readポリシーは、secret/data/duokey/*(または相当するパス)だけにスコープしたまま にしてください。ここでの最小権限とは、ESO の ServiceAccount トークンが侵害されても、Vault 内の 他のものではなく DuoKey 自身のシークレットしか読み取れないということを意味します。
ID、SSO、アクセス制御 に進むか、このパターンの一般的な (あらゆるシークレットマネージャーに対応する)バージョンについては シークレットマネージャー統合 に戻ってください。