このページでは、PodSecurity
アドミッション コントローラを使用して、Google Kubernetes Engine(GKE)クラスタで事前定義された Pod レベルのセキュリティ管理を適用する方法について説明します。
PodSecurity
の仕組みについて詳しくは、Pod のセキュリティ アドミッションをご覧ください。
概要
PodSecurity
は Kubernetes アドミッション コントローラであり、これにより GKE クラスタで実行されている Pod に Pod セキュリティ標準を適用できます。Pod セキュリティ標準は事前定義されたセキュリティ ポリシーであり、Kubernetes における Pod セキュリティの高度なニーズに対応しています。これらのポリシーは、制約の緩やかなものから非常に厳格なものまで多岐にわたります。
GKE クラスタには、次の Pod セキュリティ標準を適用できます。
- 特権: 最大レベルの権限を提供する、制限のないポリシー。既知の権限昇格を許可します。
- ベースライン: デフォルトで指定された最小限の Pod 構成を許可する最小限に抑えられたポリシー。既知の権限昇格を防止します。
- 制限付き: Pod 強化のベスト プラクティスに従う、高度に制限されたポリシー。
PodSecurity
アドミッション コントローラを使用すると、次のモードで Pod セキュリティ標準を適用できます。
- 適用: ポリシー違反により Pod の作成が拒否されます。監査イベントが監査ログに追加されます。
- 監査: ポリシー違反が監査ログに監査イベントを追加する原因になります。Pod の作成が許可されます。
- 警告: ポリシー違反がユーザー向けの警告の原因になります。Pod の作成が許可されます。
PodSecurity
アドミッション コントローラにより、これらのポリシーが Kubernetes API に埋め込まれます。
Pod レベルでカスタム セキュリティ ポリシーを作成して適用する場合は、代わりに Gatekeeper アドミッション コントローラの使用を検討してください。
始める前に
始める前に、次の作業が完了していることを確認してください。
- Google Kubernetes Engine API を有効にする。 Google Kubernetes Engine API の有効化
- このタスクに Google Cloud CLI を使用する場合は、gcloud CLI をインストールして初期化する。すでに gcloud CLI をインストールしている場合は、
gcloud components update
を実行して最新のバージョンを取得する。
- バージョン 1.23 以降を実行する GKE Autopilot または Standard クラスタがあることを確認します。
- Autopilot クラスタの場合、デフォルトのバージョンが 1.23 以降のリリース チャンネルに登録します。
- Standard クラスタの場合は、リリース チャンネルに登録するか、クラスタを特定のバージョンにアップグレードします。
要件
PodSecurity
アドミッション コントローラは、次の GKE バージョンを実行しているクラスタで使用可能で、デフォルトで有効になっています。
- バージョン 1.25 以降: 安定版
- バージョン 1.23 とバージョン 1.24: ベータ版
GKE バージョンが利用可能で、リリース チャンネルのデフォルト バージョンであるかどうかを確認するには、リリース スケジュールをご覧ください。
PodSecurity
を使用して Pod セキュリティ標準を適用する
PodSecurity
アドミッション コントローラを使用するには、特定の Pod セキュリティ標準を特定のモードで特定の名前空間に適用する必要があります。これを行うには、名前空間ラベルを使用します。この演習では、以下のことを行います。
- 2 つの新しい Namespace を作成する
- 各 Namespace にセキュリティ ポリシーを適用する
- 構成されたポリシーをテストする
次の GKE バージョンでは、GKE は kube-system
Namespace に適用するポリシーを無視します。
- 1.23.6-gke.1900 以降
- 1.24.0-gke.1200 以降
以前のバージョンの GKE では、kube-system
にポリシーを適用することは避けてください。
新しい Namespace を作成する
クラスタで Namespace を作成します。
kubectl create ns baseline-ns
kubectl create ns restricted-ns
このコマンドを実行すると、次の Namespace が作成されます。
baseline-ns
: ワークロードの制約が緩い場合restricted-ns
: ワークロードの制約が厳格な場合
ラベルを使用してセキュリティ ポリシーを適用する
次の Pod セキュリティ標準を適用します。
baseline
:warn
モードのbaseline-ns
に適用しますrestricted
:enforce
モードのrestricted-ns
に適用します
kubectl label --overwrite ns baseline-ns pod-security.kubernetes.io/warn=baseline
kubectl label --overwrite ns restricted-ns pod-security.kubernetes.io/enforce=restricted
これらのコマンドで次のような結果が得られます。
baseline-ns
Namespace でbaseline
ポリシーに違反するワークロードが許可され、クライアントに警告メッセージが表示されます。restricted-ns
Namespace でrestricted
ポリシーに違反するワークロードが拒否され、GKE によって監査ログにエントリが追加されます。
ラベルが追加されたことを確認します。
kubectl get ns --show-labels
出力は次のようになります。
baseline-ns Active 74s kubernetes.io/metadata.name=baseline-ns,pod-security.kubernetes.io/warn=baseline
restricted-ns Active 18s kubernetes.io/metadata.name=restricted-ns,pod-security.kubernetes.io/enforce=restricted
default Active 57m kubernetes.io/metadata.name=default
kube-public Active 57m kubernetes.io/metadata.name=kube-public
kube-system Active 57m kubernetes.io/metadata.name=kube-system
構成されたポリシーをテストする
PodSecurity
アドミッション コントローラが意図したとおりに動作することを確認するには、baseline
ポリシーと restricted
ポリシーに違反するワークロードを両方の Namespace にデプロイします。次のマニフェストの例では、権限昇格を許可する nginx
コンテナをデプロイしています。
次のマニフェストを
psa-workload.yaml
として保存します。apiVersion: v1 kind: Pod metadata: name: nginx labels: app: nginx spec: containers: - name: nginx image: nginx securityContext: privileged: true
マニフェストを
baseline-ns
Namespace に適用します。kubectl apply -f psa-workload.yaml --namespace=baseline-ns
出力は次のようになります。
Warning: would violate PodSecurity "baseline:latest": privileged (container "nginx" must not set securityContext.privileged=true)
baseline
ポリシーは、Pod を Namespace にデプロイすることを許可します。Pod が正常にデプロイされたことを確認します。
kubectl get pods --namespace=baseline-ns -l=app=nginx
マニフェストを
restricted-ns
Namespace に適用します。kubectl apply -f psa-workload.yaml --namespace=restricted-ns
出力は次のようになります。
Error from server (Forbidden): error when creating "workload.yaml": pods "nginx" is forbidden: violates PodSecurity "restricted:latest": allowPrivilegeEscalation != false (container "nginx" must set securityContext.allowPrivilegeEscalation=false), unrestricted capabilities (container "nginx" must set securityContext.capabilities.drop=["ALL"]), runAsNonRoot != true (pod or container "nginx" must set securityContext.runAsNonRoot=true), seccompProfile (pod or container "nginx" must set securityContext.seccompProfile.type to "RuntimeDefault" or "Localhost")
Pod は Namespace にはデプロイされません。ログに監査エントリが追加されます。
監査ログでポリシー違反を確認する
audit
モードと enforce
モードのポリシー違反は、クラスタの監査ログに記録されます。これらのログは、Google Cloud コンソールのログ エクスプローラを使用して表示できます。
Google Cloud コンソールの [ログ エクスプローラ] ページに移動します。
[クエリ] フィールドに次のものを指定して、
audit
モードとenforce
モードの監査ログを取得します。resource.type="k8s_cluster" protoPayload.resourceName:"/pods/nginx" protoPayload.methodName="io.k8s.core.v1.pods.create" (labels."pod-security.kubernetes.io/audit-violations":"PodSecurity" OR protoPayload.response.reason="Forbidden")
[クエリを実行] をクリックします。
[クエリ結果] セクションで
Forbidden
ログエントリを開いて、enforce
モードの拒否ログを調べます。詳細は次のようになります。{ ... protoPayload: { @type: "type.googleapis.com/google.cloud.audit.AuditLog" authenticationInfo: {1} authorizationInfo: [1] methodName: "io.k8s.core.v1.pods.create" request: {6} requestMetadata: {2} resourceName: "core/v1/namespaces/restricted-ns/pods/nginx" response: { @type: "core.k8s.io/v1.Status" apiVersion: "v1" code: 403 details: {2} kind: "Status" message: "pods "nginx" is forbidden: violates PodSecurity "restricted:latest": privileged (container "nginx" must not set securityContext.privileged=true), allowPrivilegeEscalation != false (container "nginx" must set securityContext.allowPrivilegeEscalation=false), unrestricted capabilities (container "nginx" must set securityContext.capabilities.drop=["ALL"]), runAsNonRoot != true (pod or container "nginx" must set securityContext.runAsNonRoot=true), seccompProfile (pod or container "nginx" must set securityContext.seccompProfile.type to "RuntimeDefault" or "Localhost")" metadata: {0} reason: "Forbidden" status: "Failure" } serviceName: "k8s.io" status: {2} } receiveTimestamp: "2022-02-01T19:19:25.353235326Z" resource: {2} timestamp: "2022-02-01T19:19:21.469360Z" }
audit-violations
ログエントリを開いて、audit
モードのログを調べます。詳細は次のようになります。{ ... labels: { ... pod-security.kubernetes.io/audit-violations: "would violate PodSecurity "baseline:latest": privileged (container "nginx" must not set securityContext.privileged=true)" pod-security.kubernetes.io/enforce-policy: "privileged:latest" } operation: {4} protoPayload: {10} receiveTimestamp: "2023-12-26T05:18:04.533631468Z" resource: {2} timestamp: "2023-12-26T05:17:36.102387Z" }
クリーンアップ
Google Cloud アカウントに課金されないようにするには、Namespace を削除します。
kubectl delete ns baseline-ns
kubectl delete ns restricted-ns
PodSecurity
の代替手段
組み込み Kubernetes PodSecurity
アドミッション コントローラを使用して Pod セキュリティ標準を適用することに加え、Gatekeeper(Open Policy Agent(OPA)ベースのアドミッション コントローラ)を使用して、カスタム Pod レベルのセキュリティ管理を作成し、適用できます。
次のステップ
- Pod のセキュリティ標準の詳細を確認する。
PodSecurity
アドミッション コントローラの詳細を確認する。- PodSecurityPolicy から
PodSecurity
アドミッション コントローラに移行する。