Gatekeeper 作為 Kubernetes 的一個關鍵安全工具,仰賴 Open Policy Agent (OPA) 提供強大的策略控制能力。本文不僅探討 Gatekeeper 的驗證、強制和變異策略機制,更輔以實際案例與程式碼片段,解析如何在 Kubernetes 環境中有效應用。從容器安全形度出發,我們會示範如何使用 SeccompProfile 限制系統呼叫,提升 Pod 安全性。此外,針對多租戶環境,文章詳細介紹如何結合 Node Taints、Tolerations 和 Affinity 等 Kubernetes 原生機制,搭配 Gatekeeper 的 Assign 和 Validation 策略,實作資源隔離和安全管控,確保不同租戶間的工作負載互不幹擾。

Gatekeeper 政策與 Kubernetes 的整合應用

Gatekeeper 是 Kubernetes 的一個重要安全工具,它透過 Open Policy Agent (OPA) 實作對叢集資源的策略控制。在本章中,我們將探討 Gatekeeper 的政策機制,包括驗證政策、強制執行動作和變異政策,並透過具體範例來說明其應用。

驗證政策與違規處理

Gatekeeper 的驗證政策用於檢查 Kubernetes 資源是否符合特定的安全要求。當資源不符合政策要求時,Gatekeeper 會記錄違規資訊。以下是一個典型的違規日誌範例:

{
  "resource_group": "apps",
  "resource_api_version": "v1",
  "resource_kind": "Deployment",
  "resource_namespace": "policy-test",
  "resource_name": "test",
  "request_username": "minikube-user"
}

內容解密:

此 JSON 物件記錄了一次違規事件的詳細資訊。其中:

  • resource_groupresource_api_version 指定了資源的 API 群組和版本。
  • resource_kind 表示資源型別為 Deployment。
  • resource_namespaceresource_name 指定了違規資源所在的名稱空間和名稱。
  • request_username 表示發起請求的使用者名稱。

在 Gatekeeper 的 Constraint 狀態列位中,也可以看到違規的詳細資訊:

totalViolations: 1
violations:
- enforcementAction: dryrun
  group: apps
  kind: Deployment
  message: 'INVALID_DEPLOYMENT_REGISTRY: BAD_REGISTRY/read-only-container:v0.0.1 image is not sourced from an authorized registry. Resource ID (ns/name/kind): policy-test/test/Deployment'
  name: test
  namespace: policy-test
  version: v1

內容解密:

此段 YAML 描述了一個違規事件:

  • totalViolations 表示總共有 1 個違規事件。
  • violations 列出了違規的詳細資訊,包括執行動作、資源群組、種類別、錯誤訊息等。
  • message 欄位明確指出映像檔 BAD_REGISTRY/read-only-container:v0.0.1 不是來自授權的登入檔。

變異政策的應用

Gatekeeper 的變異政策允許在資源建立或更新時自動修改其設定。為了啟用變異功能,我們需要在安裝 Gatekeeper Helm chart 時設定特定的引數:

--set logMutations=true --set mutationAnnotations=true

這些引數會啟用變異日誌記錄和資源註解,有助於除錯和稽核。

Gatekeeper Controller Manager 的變異引數

- args:
  - --log-mutations=true
  - --mutation-annotations=true
  - --operation=mutation-webhook

內容解密:

這些引陣列態了 Gatekeeper Controller Manager 的行為:

  • --log-mutations=true 啟用了變異日誌記錄。
  • --mutation-annotations=true 為被變異的資源新增註解。
  • --operation=mutation-webhook 指定了變異操作的型別。

變異日誌範例

當變異政策被應用時,Gatekeeper Controller Manager 會記錄相關的日誌:

{
  "level": "info",
  "ts": 1672262677.1373708,
  "logger": "mutation",
  "msg": "Mutation applied",
  "process": "mutation",
  "Mutation Id": "2e223bf5-73bb-4e55-8e75-d778d5b32cbc",
  "event_type": "mutation_applied",
  "resource_group": "",
  "resource_kind": "Pod",
  "resource_api_version": "v1",
  "resource_namespace": "policy-test",
  "resource_name": "test-pod",
  "iteration_0": "AssignMetadata//label-billing:1, AssignMetadata//label-env:1, AssignMetadata//label-owner:1"
}

內容解密:

此 JSON 物件描述了一次成功的變異操作:

  • msg 表示變異已應用。
  • Mutation Id 是此次變異的唯一識別碼。
  • resource_kindresource_name 指定了被變異的資源型別和名稱。
  • iteration_0 列出了應用的變異操作,包括新增特定的標籤。

Gatekeeper 的四種變異 CRDs

Gatekeeper 提供了四種變異 CRDs(Custom Resource Definitions)來實作不同的變異需求:

  1. assign.mutations.gatekeeper.sh:用於修改資源的中繼資料(metadata)以外的部分。
  2. assignmetadata.mutations.gatekeeper.sh:專門用於修改資源的中繼資料。
  3. modifyset.mutations.gatekeeper.sh:用於修改資源中的列表專案。
  4. assignimage.mutations.gatekeeper.sh:用於修改容器映像檔字串。

使用 AssignMetadata 變異器新增標籤

以下是一個使用 AssignMetadata 變異器的範例政策,用於為特定的 Pod 新增標籤:

apiVersion: mutations.gatekeeper.sh/v1
kind: AssignMetadata
metadata:
  name: label-owner
spec:
  match:
    scope: Namespaced
    kinds:
      - apiGroups: ["*"]
        kinds: ["Pod"]
    namespaces: ["policy*"]
  location: "metadata.labels.owner"
  parameters:
    assign:
      value: "jimmy"

圖表翻譯:

  graph LR
    A[開始] --> B[匹配 Namespaced 範圍內的 Pod 資源]
    B --> C[檢查名稱空間是否符合 policy*]
    C --> D[在 metadata.labels.owner 處指定 jimmy]
    D --> E[完成變異]

此圖示展示了 AssignMetadata 變異器的運作流程,從匹配資源到最終指定的過程。

內容解密:

此 AssignMetadata 政策的詳細說明:

  • match 部分指定了政策的匹配條件,包括範圍、資源型別和名稱空間。
  • location 指定了要修改的欄位,即 metadata.labels.owner
  • parameters.assign.value 設定了要賦予標籤的值為 "jimmy"

測試變異政策

我們可以建立一個測試 Pod 來驗證上述政策的效果:

apiVersion: v1
kind: Pod
metadata:
  name: test-pod
  namespace: policy-test
  labels:
    app: test
spec:
  containers:
    - name: test
      image: gcr.io/google-containers/pause:3.2
      imagePullPolicy: Always
      securityContext:
        allowPrivilegeEscalation: false
        runAsUser: 1000
        readOnlyRootFilesystem: true
        runAsNonRoot: true
        capabilities:
          drop: ["ALL"]
        seccompProfile:
          type: "RuntimeDefault"

套用此 Pod 設定後,我們可以檢查其標籤和註解:

$ kubectl -n policy-test get pods test-pod -o=jsonpath='{.metadata.labels}'
{"app":"test","billing":"lob-cc","env":"dev","owner":"jimmy"}

$ kubectl -n policy-test get pods test-pod -o=jsonpath='{.metadata.annotations}'
{"gatekeeper.sh/mutation-id":"2e223bf5-73bb-4e55-8e75-d778d5b32cbc",...}

圖表翻譯:

  graph LR
    A[建立 Pod] --> B[Gatekeeper 自動新增標籤]
    B --> C[檢查 Pod 的標籤和註解]
    C --> D[驗證變異結果]

此圖示展示了從建立 Pod 到驗證變異結果的整個流程。

Kubernetes 中的 OPA/Gatekeeper 策略管理與多租戶隔離實作

在現代的 Kubernetes 環境中,如何有效地管理和實施安全策略是一個重要的課題。Open Policy Agent(OPA)與 Gatekeeper 的結合提供了一種強大的策略管理機制,能夠幫助我們實作複雜的安全需求和資源隔離。本文將探討如何使用 OPA/Gatekeeper 來實作 Kubernetes 中的策略管理,特別是在多租戶隔離場景下的應用。

SeccompProfile 策略組態與實作

Seccomp(Secure Computing Mode)是一種 Linux 核心安全機制,用於限制容器內可執行的系統呼叫。在 Kubernetes 中,我們可以透過組態 SeccompProfile 來增強容器的安全性。下面是一個基礎的 Pod 組態範例:

spec:
  containers:
  - name: test-pod
    image: gcr.io/google-containers/pause:3.2
    imagePullPolicy: Always
    securityContext:
      allowPrivilegeEscalation: false
      runAsUser: 1000
      readOnlyRootFilesystem: true
      runAsNonRoot: true
      capabilities:
        drop: ["ALL"]

使用 Gatekeeper 實施 SeccompProfile 策略

為了確保所有 Pod 都組態了適當的 SeccompProfile,我們可以使用 Gatekeeper 的 Assign 策略來自動為符合特定條件的 Pod 新增必要的組態。以下是一個範例策略:

apiVersion: mutations.gatekeeper.sh/v1
kind: Assign
metadata:
  name: add-seccomp
spec:
  applyTo:
  - groups: [""]
    kinds: ["Pod"]
    versions: ["v1"]
  match:
    namespaces: ["policy*"]
  location: "spec.containers[name: *].securityContext.seccompProfile.type"
  parameters:
    pathTests:
    - subPath: "spec.containers[name: *].securityContext.seccompProfile"
      condition: MustNotExist
    assign:
      value: RuntimeDefault

策略解讀

  1. 策略匹配條件:此策略會匹配所有在名稱以 “policy” 開頭的 Namespace 中的 Pod。
  2. 自動組態 SeccompProfile:如果 Pod 的容器尚未組態 SeccompProfile,Gatekeeper 會自動將 seccompProfile.type 設定為 RuntimeDefault
  3. 路徑測試:策略中使用了 pathTests 來檢查指定的路徑是否存在,若不存在則執行指定操作。

驗證策略效果

在應用了上述策略後,我們可以透過以下命令來驗證 Pod 是否被正確修改:

kubectl -n policy-test get pods another-test-pod -o=jsonpath='{.spec.containers[].securityContext.seccompProfile}'

預期的輸出應該顯示 {"type":"RuntimeDefault"},表明 SeccompProfile 已被成功組態。

多租戶隔離實作

在多租戶的 Kubernetes 環境中,資源隔離是確保不同租戶之間工作負載安全性的關鍵。以下是一個根據 Node Taints、Tolerations 和 Affinity 的隔離方案。

實作步驟

  1. 建立多個 Node Group:首先,需要在 Kubernetes 叢集中建立多個 Node Group,每個 Node Group 對應一個租戶。
  2. 設定 Node Taints 和 Labels:為特定的 Node Group 設定 Taints 和 Labels,以便後續的排程控制。
  3. 編寫 Mutation 和 Validation 策略
    • 使用 Mutation 策略為特定 Namespace 中的 Pod 自動新增 Tolerations 和 Node Affinity。
    • 使用 Validation 策略驗證 Pod 是否具備正確的 Tolerations 和 Node Affinity。

範例組態

# Mutation 策略範例:新增 Toleration
apiVersion: mutations.gatekeeper.sh/v1
kind: Assign
metadata:
  name: add-toleration
spec:
  applyTo:
  - groups: [""]
    kinds: ["Pod"]
    versions: ["v1"]
  match:
    namespaces: ["tenant1*"]
  location: "spec.tolerations"
  parameters:
    assign:
      value:
        key: "tenant1-taint"
        operator: "Exists"
        effect: "NoSchedule"
# Validation 策略範例:驗證 Toleration
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sTolerationConstraint
metadata:
  name: toleration-constraint
spec:
  match:
    namespaces: ["tenant1*"]
  parameters:
    tolerations:
    - key: "tenant1-taint"
      operator: "Exists"

隨著 Kubernetes 和雲原生技術的不斷發展,安全策略管理將變得越來越重要。未來,我們可以期待 OPA/Gatekeeper 在以下幾個方面有更多的發展和改進:

  1. 更豐富的策略函式庫:提供更多預定義的策略範本,以滿足不同的安全需求。
  2. 更強大的策略驗證功能:增強策略驗證的能力,確保策略的有效性和正確性。
  3. 更好的整合性:與更多的 Kubernetes 生態系統工具和平台整合,提供無縫的安全管理體驗。

透過持續地探索和採用新的安全技術和實踐,我們可以更好地保護 Kubernetes 環境中的工作負載和資料。