PodSecurity を使用した Pod レベルの事前定義セキュリティ ポリシーの適用


このページでは、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 を実行して最新のバージョンを取得する。

要件

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 コンテナをデプロイしています。

  1. 次のマニフェストを psa-workload.yaml として保存します。

    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        securityContext:
          privileged: true
    
  2. マニフェストを 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 にデプロイすることを許可します。

  3. Pod が正常にデプロイされたことを確認します。

    kubectl get pods --namespace=baseline-ns -l=app=nginx
    
  4. マニフェストを 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 コンソールのログ エクスプローラを使用して表示できます。

  1. Google Cloud コンソールの [ログ エクスプローラ] ページに移動します。

    [ログ エクスプローラ] に移動

  2. [クエリ] フィールドに次のものを指定して、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")
    
  3. [クエリを実行] をクリックします。

  4. [クエリ結果] セクションで 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"
    }
    
  5. 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 セキュリティ標準を適用することに加え、GatekeeperOpen Policy Agent(OPA)ベースのアドミッション コントローラ)を使用して、カスタム Pod レベルのセキュリティ管理を作成し、適用できます。

次のステップ