このページでは、Gatekeeper アドミッション コントローラを使用して、Google Kubernetes Engine(GKE)クラスタに Pod レベルのセキュリティ管理を適用する方法を説明します。
概要
Gatekeeper は、Open Policy Agent(OPA)を使用して Kubernetes クラスタで Pod を作成および更新するリクエストを検証するためのアドミッション コントローラです。
Gatekeeper を使用すると、管理者は制約を使ってポリシーを定義できます。制約は、Kubernetes でのデプロイの動作を許可または拒否する一連の条件です。その後、ConstraintTemplate
を使用してクラスタにこのポリシーを適用できます。このドキュメントには、Gatekeeper を使用してセキュリティ ポリシーの適用、テスト、監査を確実に行うために、ワークロードのセキュリティ機能を制限する例を記載します。
Gatekeeper は、次のことも行います。
- ポリシーのロールアウト: 段階的に範囲を限定してポリシーを適用し、ワークロードの中断のリスクを抑えます。
- テスト時のポリシーの変更: ポリシー適用前に影響と範囲をテストするためのメカニズムを提供します。
- 既存のポリシーの監査: 新しいワークロードと既存のワークロードにセキュリティ管理の適用(監査制御)を行います。
コンセプト
Gatekeeper は、クラスタを強力かつ柔軟に制御する方法を管理者に提供するための 2 つのコンセプト、つまり制約と制約テンプレートを導入しています。これはどちらも、Open Policy Agent の制約フレームワークから継承したコンセプトです。
制約はセキュリティ ポリシーを表現したもので、要件と適用範囲を定義します。制約テンプレートは再利用可能なステートメント(Rego で記述)で、制約で定義された要件に基づいて、Kubernetes オブジェクト内の特定のフィールドを評価するロジックを適用します。
たとえば、特定の名前空間の Pod に適用できる許容可能な seccomp プロファイルを宣言するための制約と、これらの値の抽出と処理を行うロジックに相当する同等の制約テンプレートがあるとします。
次の制約テンプレートは、Gatekeeper リポジトリの Pod 仕様に securityContext.privileged
が存在するかどうかを確認します。
apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
name: k8spspprivilegedcontainer
spec:
crd:
spec:
names:
kind: K8sPSPPrivilegedContainer
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package k8spspprivileged
violation[{"msg": msg, "details": {}}] {
c := input_containers[_]
c.securityContext.privileged
msg := sprintf("Privileged container is not allowed: %v, securityContext: %v", [c.name, c.securityContext])
}
input_containers[c] {
c := input.review.object.spec.containers[_]
}
input_containers[c] {
c := input.review.object.spec.initContainers[_]
}
上記の制約テンプレートを拡張するために、次の制約では、dryrun
モードでのこの制約テンプレート特有の適用範囲(kinds
)を定義します。
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sPSPPrivilegedContainer
metadata:
name: psp-privileged-container
spec:
enforcementAction: dryrun
match:
kinds:
- apiGroups: [""]
kinds: ["Pod"]
Gatekeeper を使用すると、独自の制約と制約テンプレートを作成して特定のニーズに対応できます。Gatekeeper リポジトリで基準となる一連の制約と制約テンプレートを使用して、迅速な導入とセキュリティ適用を実現することもできます。各制約には Pod 構成の例も含まれています。
Google Cloud では、オープンソースの Gatekeeper のマネージド バージョン(Policy Controller)を提供し、公式にサポートしています。Google は、オープンソースの Gatekeeper プロジェクトを公式にサポートしていません。
始める前に
始める前に、次の作業が完了していることを確認してください。
- Google Kubernetes Engine API を有効にする。 Google Kubernetes Engine API の有効化
- このタスクに Google Cloud CLI を使用する場合は、gcloud CLI をインストールして初期化する。すでに gcloud CLI をインストールしている場合は、
gcloud components update
を実行して最新のバージョンを取得する。
Policy Controller を使用してクラスタで Gatekeeper を有効にする
Policy Controller は、Gatekeeper オープンソース プロジェクト上に構築されたポリシー エンジンです。Policy Controller はコードとしてのポリシー、マルチクラスタ サポート、Cloud Logging との統合、Google Cloud コンソールでのポリシーのステータスの確認などの機能を備えており、ポリシーを大規模に適用することができます。このため、Google では Policy Controller の使用をおすすめしています。Policy Controller は Google Kubernetes Engine(GKE)Enterprise エディションのライセンスで使用できますが、代わりにクラスタに Gatekeeper をインストールすることもできます。
クラスタで Policy Controller を有効にするには、Policy Controller のインストール ガイドの説明に従ってください。
制約と制約テンプレートを有効にする
Gatekeeper とその制約テンプレートは、既存のワークロードや新しいワークロードに悪影響を与えることなくインストールして有効にすることが可能です。このため、該当するすべての Pod セキュリティ制約テンプレートをクラスタに適用することをおすすめします。
さらに、Gatekeeper の制約を実装して、名前空間や Pod などの特定のオブジェクトに制御を適用することもできます。
次の例では、制約一致のステートメントで定義することで、スコープを production 名前空間に存在する Pod に制限しています。
...
spec:
match:
kinds:
- apiGroups: [""]
kinds: ["Pod"]
namespaces:
- "production"
Constraint
オブジェクトと ConstraintTemplate
オブジェクトで使用可能なオプションの詳細については、Gatekeeper の使用方法をご覧ください。
ポリシーのテスト
既存のクラスタに新しいポリシーを導入すると、動作を悪化させることがあります(たとえば、既存のワークロードを制限する場合など)。Pod セキュリティに Gatekeeper を使用する利点の 1 つは、ドライラン モードを使用して、実際に変更を行わずにポリシーの効果と影響をテストできる点です。これにより、ポリシーを適用せずに、実行中のクラスタに対してポリシー構成をテストできます。ポリシー違反はログに記録されるので、操作を妨げることなく確認できます。
次の手順は、デベロッパー、オペレータ、または管理者が制約テンプレートと制約を利用して効果や潜在的な影響を判断する方法を示しています。
監査機能とドライラン機能用のデータを複製するために Gatekeeper 構成ファイルを適用します。
kubectl create -f- <<EOF apiVersion: config.gatekeeper.sh/v1alpha1 kind: Config metadata: name: config namespace: "gatekeeper-system" spec: sync: syncOnly: - group: "" version: "v1" kind: "Namespace" - group: "" version: "v1" kind: "Pod" EOF
制約が適用されていない状態で、権限を引き上げてワークロードを実行します。
kubectl create -f- <<EOF apiVersion: v1 kind: Pod metadata: name: nginx labels: app: nginx spec: containers: - name: nginx image: nginx securityContext: privileged: true EOF
上述の
k8spspprivilegedcontainer
制約テンプレートを読み込みます。kubectl create -f- <<EOF apiVersion: templates.gatekeeper.sh/v1beta1 kind: ConstraintTemplate metadata: name: k8spspprivilegedcontainer spec: crd: spec: names: kind: K8sPSPPrivilegedContainer targets: - target: admission.k8s.gatekeeper.sh rego: | package k8spspprivileged violation[{"msg": msg, "details": {}}] { c := input_containers[_] c.securityContext.privileged msg := sprintf("Privileged container is not allowed: %v, securityContext: %v", [c.name, c.securityContext]) } input_containers[c] { c := input.review.object.spec.containers[_] } input_containers[c] { c := input.review.object.spec.initContainers[_] } EOF
次に、この制約テンプレートを拡張する新しい制約を作成します。ここでは
enforcementAction
をdryrun
に設定します。kubectl create -f- <<EOF apiVersion: constraints.gatekeeper.sh/v1beta1 kind: K8sPSPPrivilegedContainer metadata: name: psp-privileged-container spec: enforcementAction: dryrun match: kinds: - apiGroups: [""] kinds: ["Pod"] EOF
Gatekeeper が実行中のオブジェクト データを同期し、違反を受動的にチェックすることで、制約の
status
をチェックすることにより、違反が見つかったかどうか確認できます。kubectl get k8spspprivilegedcontainer.constraints.gatekeeper.sh/psp-privileged-container -o yaml
apiVersion: constraints.gatekeeper.sh/v1beta1 kind: K8sPSPPrivilegedContainer metadata: ... name: psp-privileged-container ... spec: enforcementAction: dryrun match: kinds: - apiGroups: - "" kinds: - Pod status: auditTimestamp: "2019-12-15T22:19:54Z" byPod: - enforced: true id: gatekeeper-controller-manager-0 violations: - enforcementAction: dryrun kind: Pod message: 'Privileged container is not allowed: nginx, securityContext: {"privileged": true}' name: nginx namespace: default
別の特権 Pod を実行して、ポリシーがデプロイの妨げになっていないことを確認します。
kubectl create -f- <<EOF apiVersion: v1 kind: Pod metadata: name: privpod labels: app: privpod spec: containers: - name: nginx image: nginx securityContext: privileged: true EOF
この新しい Pod が正常にデプロイされます。
このセクションで作成したリソースをクリーンアップするには、次のコマンドを実行します。
kubectl delete k8spspprivilegedcontainer.constraints.gatekeeper.sh/psp-privileged-container kubectl delete constrainttemplate k8spspprivilegedcontainer kubectl delete pod/nginx kubectl delete pod/privpod
ポリシーの適用
既存のワークロードや新しいワークロードに影響を与えずにポリシーの有効性と影響を確認できるようになったので、ポリシーを完全に適用して実装してみましょう。
上記のポリシーの検証に使用した例に基づいて、デベロッパー、オペレータ、または管理者が、制約テンプレートと制約を利用してポリシーを適用する方法について説明します。
上述の
k8spspprivilegedcontainer
制約テンプレートを読み込みます。kubectl create -f- <<EOF apiVersion: templates.gatekeeper.sh/v1beta1 kind: ConstraintTemplate metadata: name: k8spspprivilegedcontainer spec: crd: spec: names: kind: K8sPSPPrivilegedContainer targets: - target: admission.k8s.gatekeeper.sh rego: | package k8spspprivileged violation[{"msg": msg, "details": {}}] { c := input_containers[_] c.securityContext.privileged msg := sprintf("Privileged container is not allowed: %v, securityContext: %v", [c.name, c.securityContext]) } input_containers[c] { c := input.review.object.spec.containers[_] } input_containers[c] { c := input.review.object.spec.initContainers[_] } EOF
次に、この制約テンプレートを拡張する新しい制約を作成します。今回は
enforcementAction
キーを設定しません。デフォルトのenforcementAction
キーはdeny
に設定されています。kubectl create -f- <<EOF apiVersion: constraints.gatekeeper.sh/v1beta1 kind: K8sPSPPrivilegedContainer metadata: name: psp-privileged-container spec: match: kinds: - apiGroups: [""] kinds: ["Pod"] EOF
特権の承認を宣言したコンテナをデプロイします。
kubectl create -f- <<EOF apiVersion: v1 kind: Pod metadata: name: nginx labels: app: nginx spec: containers: - name: nginx image: nginx securityContext: privileged: true EOF
次のエラー メッセージが表示されます。
Error from server ([denied by psp-privileged-container] Privileged container is not allowed: nginx, securityContext: {"privileged": true}): error when creating "STDIN": admission webhook "validation.gatekeeper.sh" denied the request: [denied by psp-privileged-container] Privileged container is not allowed: nginx, securityContext: {"privileged": true}
クリーンアップするには、次のコマンドを実行します。
kubectl delete k8spspprivilegedcontainer.constraints.gatekeeper.sh/psp-privileged-container kubectl delete constrainttemplate k8spspprivilegedcontainer
Gatekeeper の代替
Gatekeeper を使用すると、カスタム Pod レベルのセキュリティ ポリシーを宣言して適用できます。Kubernetes の組み込みの PodSecurity
アドミッション コントローラを使用して、事前に定義された Pod レベルのセキュリティ ポリシーを適用することもできます。これらの事前定義ポリシーは、Pod セキュリティ標準で定義されているレベルと一致しています。
次のステップ
Gatekeeper は、宣言型ポリシーを使用して GKE クラスタにセキュリティを適用し、検証する非常に強力な手段を提供します。Gatekeeper はセキュリティだけでなく、管理や運用などの面でも使用できます。