Kubernetes 的安全管理日益複雜,Gatekeeper 提供的策略引擎有效提升了安全性,而外部資料提供者和策略擴充套件機制更進一步強化了這套框架。外部資料提供者允許 Gatekeeper 與外部系統(如 CMDB、軟體供應鏈認證)整合,實作更全面的驗證。策略擴充套件則讓 Pod 策略能自動套用至 Deployment、DaemonSet 等工作負載,避免重複設定,簡化管理流程。這兩項功能的結合,讓 Kubernetes 的安全策略管理更加靈活且易於維護。

使用外部資料提供者與策略擴充套件增強 Kubernetes 安全與管理

在 Kubernetes 環境中,OPA/Gatekeeper 提供了一套強大的策略管理機制,而外部資料提供者(External Data Provider)則進一步擴充套件了其功能,使其能夠與外部系統整合進行動態驗證和變更。本文將探討外部資料提供者的運作原理、應用案例以及 Gatekeeper 的策略擴充套件功能。

外部資料提供者的工作原理

外部資料提供者允許 Gatekeeper 在執行策略時呼叫外部服務取得額外的資料或驗證結果。這種機制使得 Kubernetes 的策略管理能夠超越叢集內部的資訊,結合外部的組態管理資料函式庫(CMDB)、軟體供應鏈認證等外部資料進行綜合判斷。

外部資料提供者的實作範例

以 Magic 8 Ball 為例,我們可以建立一個外部資料提供者服務,該服務根據輸入的容器映像 URI 傳回特定的回應。Gatekeeper 透過 ConstraintTemplate 將請求傳送至該服務,並根據回應結果決定是否允許或拒絕請求。

# ConstraintTemplate 範例
apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
  name: k8sanswersverification
spec:
  crd:
    spec:
      names:
        kind: K8sAnswerVerification
  targets:
  - target: admission.k8s.gatekeeper.sh
    rego: |
      package k8sanswersverification
      
      import data.external.data as answers
      
      violation[{"msg": msg}] {
        input.review.object.kind == "Pod"
        img := input.review.object.spec.containers[_].image
        response := answers(img)
        not response.items[0].value == "It is certain.:Y"
        msg := sprintf("invalid response: %v", [response])
      }

對應的 Constraint 定義如下:

# Answers Constraint
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sAnswerVerification
metadata:
  name: pod-answers
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Pod"]
    namespaces:
      - "policy-test"

請求與回應處理

當建立 Pod 時,Gatekeeper 會傳送請求至外部資料提供者。請求和回應的 JSON 格式如下:

// 請求範例
{
  "apiVersion": "externaldata.gatekeeper.sh/v1beta1",
  "kind": "ProviderRequest",
  "request": {
    "keys": ["gcr.io/google-containers/pause:3.2"]
  }
}

// 失敗回應範例
{
  "apiVersion": "externaldata.gatekeeper.sh/v1alpha1",
  "kind": "ProviderResponse",
  "response": {
    "idempotent": true,
    "items": [
      {
        "key": "gcr.io/google-containers/pause:3.2",
        "value": "Don't count on it.:N",
        "error": "Don't count on it.:N:DENIED"
      }
    ]
  }
}

// 成功回應範例
{
  "apiVersion": "externaldata.gatekeeper.sh/v1alpha1",
  "kind": "ProviderResponse",
  "response": {
    "idempotent": true,
    "items": [
      {
        "key": "gcr.io/google-containers/pause:3.2",
        "value": "It is certain.:Y"
      }
    ]
  }
}

外部資料提供者的應用案例

大多數外部資料提供者的使用案例集中在容器映像的變更和驗證。此外,還可以呼叫 API 對 Kubernetes 資源進行額外的驗證,例如:

  1. 組態管理資料函式庫(CMDB)驗證:將 Kubernetes 資源與 CMDB 中的組態資訊進行比對,確保資源組態的一致性。
  2. 軟體供應鏈認證:驗證容器映像是否來自可信的來源,並檢查其是否符合組織的安全標準。

策略擴充套件(Policy Expansion)功能

Gatekeeper 的策略擴充套件功能透過引入 ExpansionTemplate CRD,使得原本只針對 Pod 的策略能夠自動擴充套件至其他建立 Pod 的工作負載資源(如 Deployment、DaemonSet 等)。這樣可以避免重複編寫多個相似的策略,並且改善使用者經驗。

策略擴充套件範例

# Policy expansion example
apiVersion: expansion.gatekeeper.sh/v1alpha1
kind: ExpansionTemplate
metadata:
  name: expand-deployments
spec:
  applyTo:
    - groups: ["apps"]
      kinds:
        - "DaemonSet"
        - "Deployment"
        - "Job"
        - "ReplicaSet"
        - "ReplicationController"
        - "StatefulSet"
      versions: ["v1"]
  templateSource: "spec.template"
  enforcementAction: "warn"
  generatedGVK:
    kind: "Pod"
    group: ""
    version: "v1"

最佳實踐與注意事項

  1. 快取機制:為了避免頻繁呼叫外部資料提供者導致的網路流量問題,可以在應用程式層面實作快取機制。
  2. 超時設定:適當調整外部資料提供者和 Gatekeeper 的超時設定,以確保系統的穩定性。
  3. 錯誤處理:設計外部資料提供者時,應考慮到超時和錯誤處理機制,避免因單一元件故障影響整個叢集的運作。

隨著 Kubernetes 和雲原生技術的不斷發展,未來可以期待更多根據 OPA/Gatekeeper 的創新應用,例如更智慧的策略引擎、更豐富的外部資料源整合等。這些發展將進一步鞏固 OPA/Gatekeeper 在雲原生安全領域的重要地位。

圖表說明:外部資料提供者架構圖
  graph LR
    A[Kubernetes API] -->|請求|> B[Gatekeeper]
    B -->|呼叫外部資料|> C[外部資料提供者]
    C -->|傳回結果|> B
    B -->|根據策略判斷|> D[允許/拒絕請求]

圖表翻譯: 此圖示展示了 Kubernetes 環境中 Gatekeeper 如何透過外部資料提供者進行動態驗證的流程。首先,Kubernetes API 傳送請求至 Gatekeeper;接著,Gatekeeper 呼叫外部資料提供者取得額外資訊;最後,根據傳回結果和既定策略決定是否允許或拒絕該請求。整個流程體現了 Gatekeeper 在安全管理中的靈活性和擴充套件性。

詳細程式碼解析

以下是一個使用 Golang 編寫的簡單外部資料提供者範例,用於示範如何處理來自 Gatekeeper 的請求並傳回相應結果:

package main

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"

	"github.com/gorilla/mux"
)

// ProviderRequest represents the request from Gatekeeper
type ProviderRequest struct {
	APIversion string `json:"apiVersion"`
	Kind       string `json:"kind"`
	Request    struct {
		Keys []string `json:"keys"`
	} `json:"request"`
}

// ProviderResponse represents the response to Gatekeeper
type ProviderResponse struct {
	APIversion string `json:"apiVersion"`
	Kind       string `json:"kind"`
	Response   struct {
		Idempotent bool `json:"idempotent"`
		Items      []struct {
			Key   string `json:"key"`
			Value string `json:"value"`
			Error string `json:"error,omitempty"`
		} `json:"items"`
	} `json:"response"`
}

func main() {
	r := mux.NewRouter()
	r.HandleFunc("/validate", validateHandler).Methods("POST")
	log.Fatal(http.ListenAndServe(":8080", r))
}

func validateHandler(w http.ResponseWriter, r *http.Request) {
	var req ProviderRequest
	err := json.NewDecoder(r.Body).Decode(&req)
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	resp := ProviderResponse{
		APIversion: "externaldata.gatekeeper.sh/v1alpha1",
		Kind:       "ProviderResponse",
		Response: struct {
			Idempotent bool `json:"idempotent"`
			Items      []struct {
				Key   string `json:"key"`
				Value string `json:"value"`
				Error string `json:"error,omitempty"`
			} `json:"items"`
		}{
			Idempotent: true,
			Items:      make([]struct { Key string `json:"key"`; Value string `json:"value"`; Error string `json:"error,omitempty"` }, len(req.Request.Keys)),
		},
	}

	for i, key := range req.Request.Keys {
		// 這裡可以加入自定義的驗證邏輯
		resp.Response.Items[i].Key = key
		resp.Response.Items[i].Value = "It is certain.:Y" // 示例回應
	}

	json.NewEncoder(w).Encode(resp)
}

程式碼解析:

此 Golang 程式碼實作了一個簡單的 HTTP 服務,用於處理來自 Gatekeeper 的外部資料請求。主要步驟包括:

  1. 解析請求:將收到的 JSON 請求解析為 ProviderRequest 結構體。
  2. 生成回應:根據請求中的鍵值生成對應的回應內容,並填充到 ProviderResponse 結構體中。
  3. 傳回結果:將生成的回應編碼為 JSON 格式並傳回給 Gatekeeper。

這段程式碼展示瞭如何建立一個基本的外部資料提供者服務,並可根據具體需求擴充套件其驗證邏輯和功能。

Gatekeeper 政策擴充套件與測試

Gatekeeper 的政策擴充套件功能是一項重要的進展,它允許將 Pod 政策應用於工作負載(workloads),而無需單獨管理工作負載的政策。本文將詳細介紹 Gatekeeper 的政策擴充套件功能及其測試方法。

啟用政策擴充套件

要使用政策擴充套件功能,需要在啟動 Gatekeeper 時加入 enableGeneratorResourceExpansion 旗標。以下是一個範例的 Helm 安裝命令:

$ helm install gatekeeper gatekeeper/gatekeeper \
--namespace gatekeeper-system --create-namespace \
--set logDenies=true --set replicas=1 --set version=v3.10.0 \
--set "controllerManager.exemptNamespaces={kube-system}" \
--set enableGeneratorResourceExpansion=true

內容解密:

上述命令使用 Helm 安裝 Gatekeeper,並啟用 enableGeneratorResourceExpansion 旗標。這是啟用政策擴充套件功能的必要步驟。

測試政策擴充套件

為了測試政策擴充套件功能,我們建立了一個 ConstraintTemplateConstraint 用於禁止所有 Pod 的政策。然後,我們將一個 Deployment 資源套用到 policy-test 名稱空間。雖然 Deployment 被成功套用,但 Pod 並未啟動;Gatekeeper 向 API 伺服器發送了警告。

$ kubectl -n policy-test apply -f ../validating/tests/11-dep-reg-allow.yaml
Warning: [deny-all-pods] [Implied by expand-deployments] INPUT:
{"parameters": {}, "review": {"kind": {"group": "", "kind": "Pod", "version": "v1"}, "namespace": "policy-test", "object": {"apiVersion": "v1", "kind": "Pod",...

內容解密:

這裡的警告訊息表明 Gatekeeper 已將 Pod 政策應用於 Deployment 資源。這是透過模擬(mocking)Pod 資源並驗證其合規性來實作的。

GVK 與政策擴充套件

Gatekeeper 使用 GVK(Group, Version, Kind)來決定將哪些資源納入政策擴充套件的範圍。在上述範例中,ExpansionTemplatespec.applyTo 欄位定義了要擴充套件的 GVK。

圖表說明

  graph LR
    A[工作負載 GVK] -->|定義在 ExpansionTemplate 中|> B[Gatekeeper 擴充套件]
    B --> C[模擬 Pod 資源]
    C --> D[驗證模擬 Pod 資源]
    D --> E[將違規結果聚合到父資源]

圖表翻譯: 此圖示展示了 Gatekeeper 如何根據 GVK 定義,將政策擴充套件應用到工作負載資源上,並模擬相關的 Pod 資源進行驗證。

使用 gator CLI 測試 Gatekeeper 政策

gator(g8r)CLI 主要用於驗證 Gatekeeper 政策。以下是一個範例的測試命令:

$ gator verify suite.yaml
ok suite.yaml 0.011s
PASS

內容解密:

這裡的 suite.yaml 是一個測試套件檔案,定義了要測試的 ConstraintTemplates 和 Constraints,以及相關的測試案例。

編寫測試案例

以下是一個範例的測試套件檔案:

kind: Suite
apiVersion: test.gatekeeper.sh/v1beta1
tests:
- name: allowed-repos
  template: template.yaml
  constraint: constraint.yaml
  cases:
  - name: allowed
    object: review-good.yaml
    assertions:
    - violations: no
  - name: disallowed
    object: review-bad.yaml
    assertions:
    - violations: yes

內容解密:

這個測試套件定義了一個名為 allowed-repos 的測試,使用 template.yamlconstraint.yaml 定義的 ConstraintTemplate 和 Constraint。測試案例包括 alloweddisallowed 兩種情況,分別對應 review-good.yamlreview-bad.yaml 資原始檔。

使用 AdmissionReview 模擬測試

g8r 也支援使用 AdmissionReview 模擬作為測試輸入。以下是一個範例的 AdmissionReview 模擬:

kind: AdmissionReview
...
spec:
  containers:
  - name: test
    image: BAD_REGISTRY/read-only-container:v0.0.1

內容解密:

這個 AdmissionReview 模擬定義了一個包含不受允許的映像檔的容器,用於測試相關的政策。

隨著 Gatekeeper 和 gator CLI 的不斷發展,我們可以期待更多的功能和改進。例如,更強大的政策擴充套件功能、更豐富的測試案例和更好的整合性。這些進展將進一步鞏固 Gatekeeper 在 Kubernetes 安全領域的地位。