使用 Gatekeeper 套用自訂 Pod 層級安全性政策

本頁說明如何使用 Gatekeeper 准入控制器,將 Pod 層級的安全控管措施套用至 Google Kubernetes Engine (GKE) 叢集。本頁說明如何使用 Gatekeeper 套用限制,以便套用安全政策,協助機構滿足安全需求。

本頁適用於想對 GKE 叢集套用安全控管措施的安全性專家。如要進一步瞭解我們在內容中提及的常見角色和範例工作,請參閱「常見的 GKE 使用者角色和工作」。 Google Cloud

閱讀本頁面之前,請務必先熟悉下列概念:

Gatekeeper 總覽

Gatekeeper 是一種許可控制器,可使用 Open Policy Agent (OPA),驗證在 Kubernetes 叢集中建立及更新 Pod 的要求。

管理員可使用 Gatekeeper 透過限制定義政策,這是一組條件,可允許或拒絕 Kubernetes 中的部署行為。接著,您可以使用 ConstraintTemplate 在叢集上強制執行這些政策。本文提供相關範例,說明如何限制工作負載的安全功能,確保使用 Gatekeeper 強制執行、測試及稽核安全政策。

Gatekeeper 還能執行下列操作:

  • 推出政策:逐步強制執行政策,並限制範圍,以降低工作負載中斷的風險。
  • 試行政策變更:提供機制,在強制執行前測試政策影響和範圍。
  • 稽核現有政策:確保安全性控管機制適用於新舊工作負載 (稽核控管機制)。

Gatekeeper 重要概念

為提供強大且彈性的叢集控管方式,Gatekeeper 導入了兩個概念:限制限制範本,這兩個概念都承襲自 Open Policy Agent Constraint Framework

限制代表您的安全政策,可定義強制執行的需求和範圍。限制範本是可重複使用的陳述式 (以 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[_]
        }

如要擴充先前的限制範本範例,下列限制會定義範圍 (kinds),以便在 dryrun 模式中強制執行這個限制範本:

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 開放原始碼專案為基礎建構的政策引擎。Google 建議使用 Policy Controller,因為這項工具提供額外功能,有助於大規模強制執行政策,包括政策即程式碼、多叢集支援、與 Cloud Logging 整合,以及在 Google Cloud 控制台中查看政策狀態。Policy Controller 適用於 GKE,但您也可以在叢集上安裝 Gatekeeper

如要在叢集上啟用 Policy Controller,請按照 Policy Controller 安裝指南操作。

啟用限制和限制範本

安裝及啟用 Gatekeeper 和其限制範本時,不會對現有或新的工作負載造成負面影響。因此,建議您將所有適用的 Pod 安全性限制範本套用至叢集。

此外,您也可以實作 Gatekeeper 限制,針對特定物件 (例如命名空間和 Pod) 強制執行控管措施。

請參閱以下範例,在限制比對陳述式中定義範圍,將範圍限制為位於「production」命名空間中的「Pods」

...
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Pod"]
    namespaces:
      - "production"

如要進一步瞭解 ConstraintConstraintTemplate 物件的可用選項,請參閱「如何使用 Gatekeeper」。

測試政策

在現有叢集中導入新政策可能會導致不良行為,例如限制現有工作負載。使用 Gatekeeper 確保 Pod 安全的一項優點是,您可以使用模擬測試模式,測試政策的效力和影響,而不必實際變更。這樣一來,您就能針對執行中的叢集測試政策設定,而不必強制執行。系統會記錄並找出違反政策的行為,不會受到干擾。

下列步驟說明開發人員、營運人員或管理員如何套用限制範本和限制,判斷其效力或潛在影響:

  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
    
  2. 不套用任何限制,以進階權限執行工作負載:

    kubectl create -f- <<EOF
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        securityContext:
          privileged: true
    EOF
    
  3. 載入先前的 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
    
  4. 建立新的限制條件,即可擴充這個限制範本。這次請將 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
    
  5. 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
    
  6. 如要確認政策不會干擾部署作業,請執行另一個具備權限的 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 會成功部署。

  7. 如要清除本節中建立的資源,請執行下列指令:

    kubectl delete k8spspprivilegedcontainer.constraints.gatekeeper.sh/psp-privileged-container
    kubectl delete constrainttemplate k8spspprivilegedcontainer
    kubectl delete pod/nginx
    kubectl delete pod/privpod
    

執行政策

現在您可以在不影響現有或新工作負載的情況下,確認政策的效力和影響,因此可以全面強制執行政策。

以驗證上述政策的範例為基礎,下列步驟說明開發人員、營運人員或管理員如何套用限制範本和限制,以強制執行政策:

  1. 載入先前提及的 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
    
  2. 建立新的限制條件,即可擴充這個限制範本。這次請勿設定 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
    
  3. 嘗試部署聲明特殊權限的容器:

    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}
    
  4. 如要清除,請執行下列指令:

    kubectl delete k8spspprivilegedcontainer.constraints.gatekeeper.sh/psp-privileged-container
    kubectl delete constrainttemplate k8spspprivilegedcontainer
    

Gatekeeper 的替代方案

您可以透過 Gatekeeper 宣告及套用自訂 Pod 層級安全性政策。您也可以使用 Kubernetes 內建的PodSecurity許可控制器,套用預先定義的 Pod 層級安全性政策。這些預先定義的政策符合 Pod 安全性標準定義的層級。

後續步驟

Gatekeeper 提供非常強大的方法,可使用宣告式政策,在 GKE 叢集上強制執行及驗證安全性。不過,Gatekeeper 的用途不只在於安全,還可用於管理和營運的其他方面。