Kubernetes 的普及帶動了容器化應用程式的快速發展,但也引入了新的安全和管理挑戰。Open Policy Agent (OPA) 作為一個通用的策略引擎,可以協助解決這些挑戰。kube-mgmt 則扮演了 Kubernetes 與 OPA 之間的橋樑,負責將 Kubernetes 的策略和資料載入到 OPA,讓 OPA 能夠根據這些資訊做出決策。kube-mgmt 能夠編譯 Rego 策略,並在編譯成功後將其載入至 OPA,同時也支援從 ConfigMap 和 Kubernetes 叢集中取得資料,提供更豐富的策略決策依據。透過埠轉發或獨立 Pod,開發者可以驗證 OPA 中的資料和策略,確保組態正確。此外,文章也提供 Rego 策略撰寫的最佳實踐和注意事項,例如安全組態、監控與日誌,以及策略測試,協助開發者更好地運用 kube-mgmt 和 OPA 管理 Kubernetes 叢集。

Kubernetes 與 Open Policy Agent (OPA) 的整合管理

Kube-mgmt 的角色與功能

Kube-mgmt 作為 Kubernetes 與 OPA 之間的橋樑,主要負責將 Kubernetes 中的策略和資料載入到 OPA 中。其預設標籤和值在啟動時被設定。Kube-mgmt 編譯 Rego 策略,並在編譯成功後將策略載入到 OPA。

編譯與載入策略的過程

當 kube-mgmt 啟動時,它會嘗試編譯和載入策略到 OPA。以下是一些可能的控制檯輸出範例,展示了編譯和載入過程中的成功與失敗情況:

# kube-mgmt 無法連線到 OPA
openpolicyagent.org/kube-mgmt-status: '{"status":"error","error":{"Op":"Put","URL":"http://localhost:8181/v1/policies/opa/opa-default-system-main/main","Err":{"Op":"dial","Net":"tcp","Source":null,"Addr":{"IP":"127.0.0.1","Port":8181,"Zone":""},"Err":{"Syscall":"connect","Err":111}}}}'

# 策略編譯失敗
openpolicyagent.org/kube-mgmt-status: '{"status":"error","error":{"code":"invalid_parameter","message":"error(s) occurred while compiling module(s)","errors":[{"code":"rego_parse_error","message":"unexpected minus token: expected number","location":{"file":"opa/opa-default-system-main/main","row":13,"col":7},"details":{"line":"uid---= input.request.uid","idx":6}}]}}'

# kube-mgmt 成功編譯並載入策略
openpolicyagent.org/kube-mgmt-status: '{"status":"ok"}'

載入 Kubernetes 資料到 OPA

Kube-mgmt 不僅能載入策略,還能將 Kubernetes 資料載入到 OPA。這對於需要更多資料來進行策略決策的情況非常有用。例如,若要編寫策略以防止重複的 Kubernetes 資源,則需要叢集中的資源資料。

Kube-mgmt 的資料來源

Kube-mgmt 可以從 ConfigMap 和 Kubernetes 叢集資料中取得資料。當 kube-mgmt 上線時,它會啟動其 ConfigMap 處理器,嘗試從 Kubernetes 讀取資料,並將策略和資料載入到 OPA。

# kube-mgmt 日誌 - ConfigMap 載入器和 Kubernetes
$ kubectl logs opa-7f5f5f645-xqsv4 -c kube-mgmt
time="2024-03-08T20:09:27Z" level=info msg="Policy/data ConfigMap processor connected to K8s: namespaces=[opa]"
time="2024-03-08T20:09:27Z" level=info msg="Initial informer sync for v1/namespaces completed, took 103.300667ms"
time="2024-03-08T20:09:27Z" level=info msg="Syncing v1/namespaces."
time="2024-03-08T20:09:27Z" level=info msg="Loaded 5 resources of kind v1/namespaces into OPA. Took 502.791μs"

驗證 OPA 中的資料和策略

為了驗證 Kubernetes 資源是否已成功複製到 OPA,可以透過查詢 v1/data API 來進行驗證。首先,需要使用埠轉發將本地埠轉發到 OPA 容器的埠:

# 將本地埠轉發到 OPA 容器埠
$ kubectl -n opa port-forward pods/opa-7689cd4bd7-tlrhq 8080:8181

然後,可以使用 curl 命令查詢 OPA 的資料 API:

# 查詢 OPA 資料 API
$ curl localhost:8080/v1/data

此外,也可以透過執行一個獨立的 Pod 並使用 curl 命令查詢 OPA 服務來驗證:

# 執行一個 Pod 來存取 OPA 服務
$ make run-debugger-pod
kubectl run -n opa -it debugger --image=jimmyraywv/debugger:v0.1.0 --restart=Never

在 Pod 中,可以使用以下命令查詢 OPA 資料 API:

# 從不同的 Pod 查詢 OPA 資料 API
$ curl -k https://opa.opa.svc/v1/data

載入 ConfigMap 中的資料到 OPA

除了複製叢集資源,Kube-mgmt 還可以從 ConfigMap 中載入資料。例如,可以建立一個包含專案資料的 ConfigMap,並將其載入到 OPA:

# 包含要載入到 OPA 的專案資料的 ConfigMap
kind: ConfigMap
apiVersion: v1
metadata:
  name: opa-data-projects
  namespace: opa
  labels:
    app: opa
    billing: lob-cc
    env: dev
    owner: jimmy
    openpolicyagent.org/data: opa

隨著 Kubernetes 和 OPA 的不斷發展,Kube-mgmt 的功能也將繼續擴充套件,以滿足日益增長的安全和管理需求。未來,我們可以期待更多的功能和改進,以進一步簡化 Kubernetes 中的策略管理和資料處理。

圖表說明

  graph LR;
    A[Kubernetes Cluster] -->|Data|> B[Kube-mgmt];
    B -->|Policies|> C[OPA];
    B -->|Data|> C;
    C -->|Policy Decisions|> D[Kubernetes API Server];

圖表翻譯: 此圖示展示了 Kubernetes 叢集、Kube-mgmt 和 OPA 之間的關係。Kube-mgmt 從 Kubernetes 叢集取得資料,並將策略和資料載入到 OPA。OPA 然後根據這些策略和資料進行決策,並將結果傳回給 Kubernetes API 伺服器。

詳細內容解密:

此圖表闡述了 Kube-mgmt 如何作為橋樑連線 Kubernetes 與 OPA。它展示了 Kube-mgmt 如何從 Kubernetes 取得資料,並將其與策略一同載入到 OPA 中。隨後,OPA 利用這些資料和策略進行決策,並影響 Kubernetes API 伺服器的行為。

程式碼範例與詳細解說

以下是一個簡單的 Rego 策略範例,用於檢查 Kubernetes 資源是否具有特定的標籤:

package kubernetes.admission

deny[{"msg": msg}] {
    input.request.kind.kind == "Deployment"
    not input.request.object.metadata.labels["app.kubernetes.io/name"]
    msg := "Deployment must have 'app.kubernetes.io/name' label"
}

詳細內容解密:

此 Rego 策略檢查進入 Kubernetes 的 Deployment 資源是否具有 app.kubernetes.io/name 標籤。如果沒有,則拒絕該資源並傳回錯誤訊息。這個範例展示瞭如何使用 Rego 編寫簡單的策略來控制 Kubernetes 資源。

最佳實踐與注意事項

  1. 安全組態:確保 Kube-mgmt 和 OPA 的安全組態,避免未授權的存取。
  2. 監控與日誌:定期監控 Kube-mgmt 和 OPA 的日誌,以發現潛在的問題。
  3. 測試策略:在佈署到生產環境之前,充分測試 Rego 策略,以確保其正確性和有效性。

透過遵循這些最佳實踐,可以更好地利用 Kube-mgmt 和 OPA 管理和控制 Kubernetes 叢集中的資源。

使用kube-mgmt管理OPA資料與安全設定

在前面的章節中,我們已經瞭解瞭如何使用kube-mgmt來管理Open Policy Agent(OPA)的資料。接下來,我們將探討如何確保OPA的安全性,同時允許Kubernetes和kube-mgmt在需要時存取OPA。

OPA AuthZ與kube-mgmt

當OPA僅用於變更和驗證Kubernetes API伺服器請求時,應使用AuthZ策略來確保安全性。AuthZ策略可以防止除Kubernetes API伺服器外的客戶端存取OPA伺服器,從而保護OPA策略和資料免受未經授權的存取。

Rego策略範例

以下是一個用於保護OPA的Rego策略範例,來自kube-mgmt的README.md檔案:

package system.authz

# 預設拒絕存取
default allow := false

# 允許匿名存取特定的決策入口點
allow {
    input.path == ["v0", "data", "example", "response"]
    input.method == "POST"
}

# 允許匿名存取預設決策
allow {
    input.path == [""]
    input.method == "POST"
}

# 用於liveness和readiness探針的健康檢查
allow {
    input.path == ["health"]
    input.method == "GET"
}

# 用於Prometheus指標
allow {
    input.path == ["metrics"]
    input.method == "GET"
}

# kube-mgmt用於PUT/PATCH /v1/data和PUT/DELETE /v1/policies
allow {
    input.identity == "$TOKEN"
}

策略說明

此策略根據多個條件授權存取:

  • 匿名POST到組態的或預設的決策入口點
  • 匿名GET健康端點
  • 匿名GET指標端點
  • kube-mgmt使用正確的AuthZ令牌存取OPA API

組態AuthZ

要使用上述AuthZ策略,OPA和kube-mgmt需要額外的組態項來載入策略和存取所需的令牌。以下是一個YAML組態範例:

spec:
  containers:
  - name: opa
    image: openpolicyagent/opa:0.47.3-rootless
    args:
    - "run"
    - "--server"
    - "--tls-cert-file=/certs/tls.crt"
    - "--tls-private-key-file=/certs/tls.key"
    - "--addr=0.0.0.0:443"
    - "--addr=http://127.0.0.1:8181"
    - "--authentication=token"
    - "--authorization=basic"
    - "/policies/authz.rego"
    - "--ignore=.*"
    volumeMounts:
    - readOnly: true
      mountPath: /certs
      name: opa-server
    - readOnly: true
      mountPath: /policies
      name: inject-policy
  - name: kube-mgmt
    image: openpolicyagent/kube-mgmt:7.3.0
    args:
    - "--replicate-cluster=v1/namespaces"
    - "--replicate=extensions/v1/ingresses"
    - "--opa-auth-token-file=/policies/token"
    volumeMounts:
    - readOnly: true
      mountPath: /policies
      name: inject-policy
  volumes:
  - name: opa-server
    secret:
      secretName: opa-server
  - name: inject-policy
    secret:
      secretName: inject-policy

組態說明

此組態設定了OPA和kube-mgmt的AuthZ,使用了authentication=tokenauthorization=basic設定。同時,也設定了AuthZ令牌檔案的路徑。

Kubernetes策略

如前所述,儲存在正確標籤的Kubernetes ConfigMap中的OPA Rego策略會透過kube-mgmt側車載入到OPA中。以下是一個用於資源驗證的Rego策略範例:

package kubernetes.admission

import future.keywords.in

deny[msg] {
    input.request.kind.kind == "Pod"
    input.request.operation in ["CREATE", "DELETE", "UPDATE"]
    msg = sprintf("Request object: %q", [input.request.object])
}

策略說明

此策略匹配Pod資源,並拒絕所有CREATE、DELETE或UPDATE操作的請求。

程式碼範例:使用Rego語言撰寫Kubernetes准入控制策略
package kubernetes.admission

deny[msg] {
    input.request.kind.kind == "Pod"
    msg = sprintf("Pods are not allowed: %v", [input.request.object.metadata.name])
}

deny[msg] {
    input.request.kind.kind == "Deployment"
    input.request.object.spec.template.spec.containers[_].image != "alpine:latest"
    msg = sprintf("Deployment %v is not using the approved image", [input.request.object.metadata.name])
}

內容解密:

  1. 策略套件定義package kubernetes.admission 定義了這個Rego策略屬於 kubernetes.admission 套件,用於處理Kubernetes的准入控制。
  2. 拒絕規則deny[msg] 定義了一條拒絕規則,當條件滿足時,會拒絕請求並傳回訊息 msg
  3. 條件檢查:第一條規則檢查請求的資源是否是Pod,如果是,則拒絕請求並傳回訊息。
  4. 映像檔檢查:第二條規則檢查Deployment資源是否使用了指定的映像檔,如果沒有,則拒絕請求並傳回訊息。
  5. 訊息格式化sprintf 函式用於格式化錯誤訊息,包含請求物件的詳細資訊。

MermaidOPA決策流程

  graph LR;
    A[請求進入] --> B{檢查資源型別};
    B -->|Pod| C[拒絕請求];
    B -->|Deployment| D{檢查映像檔};
    D -->|未批准| E[拒絕請求];
    D -->|已批准| F[允許請求];

圖表翻譯:

此圖表展示了OPA的決策流程。當請求進入時,OPA首先檢查資源型別。如果是Pod,則直接拒絕請求。如果是Deployment,則進一步檢查映像檔是否已批准。如果未批准,則拒絕請求;如果已批准,則允許請求。

隨著Kubernetes和OPA的不斷發展,未來可能會出現更多增強准入控制和策略管理的功能。開發者可以關注最新的OPA和Kubernetes版本,以瞭解新的功能和改進。