Kubernetesクラスターにおけるシークレットと機密データ管理のベストプラクティス
RBAC、etcd暗号化、安全なマウント、外部シークレットストア、CSIドライバー、ローテーションでKubernetesシークレットを保護します。
Kubernetesクラスターにおけるシークレットと機密データ管理のベストプラクティス
Kubernetesシークレットは便利ですが、オブジェクト名がSecretだからといって自動的に安全になるわけではありません。RBACが広すぎたり、etcdが暗号化されていない場合、漏洩したトークンがクラスター全体のデータベースパスワード、APIキー、プライベート証明書を公開する可能性があります。
Kubernetesシークレットを1つのレイヤーとして使用し、暗号化、アクセス制御、より安全な注入パターン、およびリスクが正当化される場合は外部シークレットストアを追加します。
Kubernetesシークレットの理解:デフォルトのメカニズム
Kubernetesは、機密情報を保持するために特別に設計されたSecretオブジェクトを導入します。便利ですが、セキュリティに関するその制限とデフォルトの動作を理解することが重要です。
デフォルトの動作と注意点
デフォルトでは、Kubernetesシークレットはetcd(すべての構成データのクラスターのバッキングストア)内で保存時に暗号化されません。これらは単にBase64エンコードされており、実際の暗号化は提供しません。etcdデータストアにアクセスできる人(例:クラスター管理者、侵害されたノード)は、これらの値を簡単にデコードできます。
警告: 暗号化対策を適用せずに、機密性の高いデータに対してデフォルトのKubernetesシークレットオブジェクトのみに依存しないでください。
Base64エンコードと暗号化
Base64エンコードがセキュリティを提供するというのはよくある誤解です。Base64はエンコード方式であり、暗号化方式ではありません。簡単に元に戻せます:
# Kubernetesシークレット値をデコードする例
echo 'c3VwZXItc2VjcmV0Cg==' | base64 -d
# 出力: super-secret
レイヤー1:保存時のシークレットの保護(etcd暗号化)
シークレットを保護するための最も基本的なステップは、ストレージ層(etcd)で確実に暗号化することです。これにより、基盤となるデータベースに直接アクセスされた場合でもデータが保護されます。
保存時の暗号化の有効化
保存時の暗号化は、EncryptionConfigurationオブジェクトを使用してKubernetes APIサーバーを介して構成されます。この構成は、etcdに保存されるさまざまなタイプのデータ(secretsを含む)を暗号化するために使用するプロバイダーを指定します。
暗号化構成の主要コンポーネント:
kind: EncryptionConfiguration:リソースタイプを宣言します。resources:暗号化するAPIリソースを指定します。providers:暗号化メカニズムを定義します。一般的なプロバイダーには、aescbc、aesgcm、およびKMSプロバイダー(AWS KMSやGCP KMSなど)が含まれます。
ベストプラクティス: プラットフォームがサポートしている場合は、KMSプロバイダーを使用します。ローカルキーを使用する場合は、キーローテーションを慎重に管理し、既存のデータが再暗号化されるまで古いキーを利用可能にしておきます。
レイヤー2:転送中および使用中のシークレットの保護
etcd暗号化は「保存時」の問題を解決しますが、シークレットはPodにマウントされるときにKubeletによって復号化されます。これらのシークレットがどのように、どこに表示されるかを制御する必要があります。
戦略1:シークレットのボリュームマウント
シークレットデータをコンテナに注入する標準的な方法は、ボリュームとしてマウントすることです(多くの場合、コンテナのファイルシステムにファイルが作成されます)。
apiVersion: v1
kind: Pod
metadata:
name: secure-app
spec:
containers:
- name: my-container
image: nginx
volumeMounts:
- name: secret-volume
mountPath: "/etc/config/db"
readOnly: true
volumes:
- name: secret-volume
secret:
secretName: my-sensitive-secret
セキュリティ上の考慮事項: マウントされたシークレットボリュームは通常、Linuxノードでtmpfsによってバックアップされますが、値はコンテナプロセスや、十分なノードまたはPodアクセス権を持つ誰にでも表示されます。readOnly: trueを使用し、環境や構成ファイルをログにダンプしないようにし、本番Podへのシェルアクセスを制限します。
戦略2:環境変数(機密性の高いものには推奨されません)
便利ですが、シークレットから取得した環境変数を使用することは、一般的に価値の高いシークレットには推奨されません。環境変数は、以下を通じて簡単に漏洩する可能性があります:
- 設定が不十分なアプリケーションによって生成されたコンテナログ。
- コンテナ内または他の特権コンテナから
/proc/1/environを読み取る。 - コンテナ検査ツール。
どうしても必要な場合にのみ、機密性の低い構成データに環境変数を使用します。
レイヤー3:外部シークレットストアを使用した高度な管理
最も安全なパターンは、機密データをKubernetesコントロールプレーン(etcd)の完全に外部に保持し、専用のツールを使用して実行時に動的に取得することです。
外部シークレットオペレーターの使用
外部シークレットオペレーターは、専用のボールト(HashiCorp Vault、AWS Secrets Manager、Azure Key Vaultなど)に安全に保存されたシークレットと、ネイティブのKubernetesシークレットオブジェクトとの間のギャップを埋めます。
- 保存: 実際のシークレットは外部ボールトにのみ存在します。
- 同期/注入: オペレーターがカスタムリソース(
ExternalSecretなど)を監視し、ボールトからデータを取得します。 - 作成: オペレーターは、Podにマウントできる標準のKubernetes
Secretオブジェクトをローカルに作成します。
利点: 信頼できる情報源はクラスターの外部に残り、ローテーションと監査可能性が向上します。ただし、同期されたKubernetesシークレットは依然としてクラスター内に存在するため、RBAC、etcd暗号化、および名前空間の分離が依然として必要です。
Secrets Store CSIドライバーの使用
シークレットをetcdにローカルに保存せずに、直接かつ一時的にアクセスする必要があるアプリケーションには、Secrets Store CSIドライバーが最適な選択肢です。
- ドライバーはプロバイダー(例:Vaultプロバイダー、Azureプロバイダー)を活用します。
- 外部ストアからPodのファイルシステムに一時ボリュームとしてシークレットを直接マウントし、シークレットデータをetcdに書き込む必要を完全に回避します。
これにより、etcdデータベースからシークレットを完全に排除することで、最高レベルのセキュリティを提供します。
シークレット管理の運用ベストプラクティス
技術的なストレージメカニズムに加えて、運用上の衛生状態は、安全な姿勢を維持するために重要です。
1. 最小権限の原則(PoLP)
Podに関連付けられたサービスアカウントが、必要な特定のシークレットを読み取る権限のみを持ち、それ以外は持たないようにします。ロールベースのアクセス制御(RBAC)を使用して、権限を厳密にスコープします。
2. シークレットを頻繁にローテーションする
すべての認証情報に対して自動ローテーションスケジュールを実装します。長期間有効なシークレットは、侵害の機会を増やします。外部ボールトと統合されたツールは、このローテーションを自動的に処理することがよくあります。
3. アクセスを監査および監視する
シークレットオブジェクトを誰が読み取ったり変更したりするかを追跡するために、監査ログを構成します。外部ボールト(VaultエージェントやCSIドライバーなど)と統合されたツールは、外部ストアへのアクセス試行もログに記録する必要があります。
4. シークレットをGitにコミットしない
これは基本ルールです。プライベートリポジトリであっても、生のシークレットやBase64エンコードされたシークレットをGitリポジトリに保存しないでください。git-secretsなどのツールや、構成管理テンプレートツール(HelmやKustomizeなど)を外部シークレット注入メカニズムと組み合わせて使用し、デプロイメントマニフェストを管理します。
Kustomizeを使用した例(外部参照):
テンプレートを使用する場合、マニフェストファイルにプレースホルダーを使用し、ビルドステップまたはCI/CDパイプラインに依存して、YAMLをクラスターに適用する前に、ボールトから安全に取得した実際のシークレット値を注入することがあります。
管理戦略の比較
| 戦略 | セキュリティレベル | etcd露出? | 複雑さ | 最適な用途 |
|---|---|---|---|---|
| デフォルトのK8sシークレット(etcd暗号化なし) | 非常に低い | はい(平文) | 低い | 一時的なテストのみ |
| etcd暗号化を使用したK8sシークレット | 中程度 | はい(暗号化) | 中程度 | 一般的な構成データ |
| 外部シークレットオペレーター | 高い | はい(オペレーター管理のシークレット) | 高い | シークレット管理の標準化 |
| Secrets Store CSIドライバー | 最高 | いいえ(直接マウント) | 高い | 機密性の高い認証情報とトークン |
etcd暗号化を有効にし、RBACを強化することから始めます。次に、各ワークロードが同期されたシークレット、直接CSIマウント、または外部ボールトからの動的認証情報のどれを使用できるかを決定します。最適な設定は、誰がシークレットを読み取れるか、どこに保存されるか、露出後にどの程度有用であり続けるかを制限するものです。