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


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

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

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

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 適用於 Google Kubernetes Engine (GKE) Enterprise 版授權,但您也可以在叢集上安裝 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 的用途不只在於安全,還可用於管理和營運的其他方面。