Kubernetesの防御的要塞:Admission Controllerによる「不可視の境界線」の設計
Kubernetesの堅牢性は、APIサーバーへの到達点である「Admission Controller」をいかに制御するかにかかっている。多くの組織が「セキュアな設定」をドキュメントで強いるが、現場のDevOpsは容赦なく脆弱なコンテナをデプロイする。性善説に基づくガバナンスは、サイバー攻撃者にとって格好の餌食だ。
今日は、OPA GatekeeperやKyvernoを用い、Kubernetesクラスターの深層に「強制的な防衛レイヤー」を埋め込むための、レッドチーム視点からのアーキテクチャ論を語ろう。
—
1. なぜ「設定の自動修正」だけでは不十分なのか
多くの開発者は、Policy-as-Codeを単なる「静的解析ツール」のように捉えている。しかし、真の防御者は、これがAPIリクエストのインターセプター(中間攻撃者的な立ち位置)であることを理解している。
攻撃者は、特権昇格や水平展開を狙う際、PodのSecurityContextを巧妙に操作する。例えば、hostPathマウントによるノードへの脱出や、allowPrivilegeEscalation: trueを用いたカーネル脆弱性の突き上げだ。これらは、クラスターの外側にあるCI/CDパイプラインでのスキャンだけでは検知しきれない。最終的なAPIサーバーへの書き込み直前で、バイナリレベルで弾く必要がある。
2. OPA Gatekeeper:Regoによる論理的強制
OPA Gatekeeperは、宣言的なポリシー言語「Rego」を用いて、APIリクエストを決定論的に制御する。ここで重要なのは、単に禁止するのではなく、「攻撃のコンテキストを考慮した拒絶」を行うことだ。
以下は、特権コンテナの起動を完全に遮断し、かつ特定のラベルがない名前空間へのデプロイを拒否するRegoの構成例である。
package k8spspprivilegedcontainer
# 特権コンテナのデプロイを拒否するロジック
violation[{"msg": msg}] {
input.review.object.spec.containers[_].securityContext.privileged == true
msg := "特権モードでのコンテナ実行は禁止されています。カーネル空間へのアクセスを制限してください。"
}
# 特定ラベル(prod)がない名前空間へのリソース投入を拒否
violation[{"msg": msg}] {
not input.review.object.metadata.labels["environment"] == "prod"
msg := "本番環境の名前空間には環境ラベルが必要です。"
}
このポリシーをConstraintTemplateとしてデプロイすることで、APIサーバーはリクエストを受け取った瞬間に評価を行い、違反があれば即座に403 Forbiddenを返す。これは、パケットレベルのフィルタリングと同様に、攻撃者の足掛かりを物理的に無効化する。
3. Kyverno:Kubernetesネイティブな防御の利点
KyvernoはRegoの学習コストを嫌う現場に向いているが、その真価は「ミューテーション(自動修正)」にある。例えば、開発者が忘れたReadOnlyRootFilesystemを、デプロイ時に強制的に上書きする挙動だ。
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: enforce-read-only-root-filesystem
spec:
validationFailureAction: Enforce # 違反時は即座に拒否
rules:
- name: set-read-only-root
match:
resources:
kinds:
- Pod
mutate:
patchStrategicMerge:
spec:
containers:
- (name): "*"
securityContext:
readOnlyRootFilesystem: true # 開発者が忘れても強制的に適用
この手法の強みは、「開発者のワークフローを破壊せずに、セキュリティレベルを底上げできる」点にある。攻撃者が任意のバイナリをコンテナ内にダウンロードし、実行権限を与えようとしても、ファイルシステムが書き込み禁止であれば、永続化(Persistence)の試みは失敗に終わる。
4. プロンプトインジェクションとAdmission Controlの意外な接点
現在、多くのLLMアプリケーションがK8s上で動作している。ここで懸念すべきは、アプリケーションの推論結果がそのままAPI操作に直結するケースだ。もしLLMが乗っ取られ、悪意あるプロンプトがkubectl的な挙動を誘発した場合、Admission Controllerが最後の防衛線となる。
LLMが出力したJSONペイロードに対して、KubernetesのAdmission Controllerが「このPodは外部ネットワークへのアクセス権限を持っていない」と判断すれば、インジェクションによる外部へのデータ持ち出し(Data Exfiltration)は阻止できる。つまり、Admission ControllerはLLMに対する「ガードレイル」として機能するのだ。
結論:防御の多層化がもたらす余裕
セキュリティアーキテクトに求められるのは、単一のツールへの依存ではない。
- OPA/KyvernoでAPI層を塞ぐ。
- eBPF(Ciliumなど)でネットワーク層の不審な挙動を検知する。
- コンテナランタイム(gVisorなど)でカーネルとの隔離を強化する。
これらが噛み合ったとき、初めて攻撃者は「クラスターという迷路」の中で息絶えることになる。完璧な防御など存在しないが、侵入者に対して「コストが見合わない」と思わせるための障壁を、Admission Controllerという最強のツールで構築し続けよう。
これが、我々レッドチームが「突破不可能」な要塞を設計する際の、唯一のセオリーである。
コメント