返回文章列表

Kubernetes PodSecurityPolicies 與 OPA 安全策略

本文探討如何在 Kubernetes 中使用 PodSecurityPolicies(PSP)以及 Open Policy Agent(OPA)增強安全性。文章涵蓋 PSP 的建立、應用、除錯,以及使用 kube-psp-advisor 工具簡化 PSP 的生成過程。此外,也介紹了 OPA 和 GateKeeper

Kubernetes 資安

Kubernetes 的安全性至關重要,PodSecurityPolicies 提供了基本的 Pod 層級安全控制,但設定和管理較為複雜。透過 kube-psp-advisor 等工具可以簡化 PSP 的生成,但仍需手動調整與佈署。更進階的安全性需求則可以透過 Open Policy Agent(OPA)和 GateKeeper 來滿足。OPA 提供了更靈活且強大的策略引擎,使用 Rego 語言編寫策略,能更精細地控制 Kubernetes 叢集的行為。GateKeeper 作為 Kubernetes 原生專案,簡化了 OPA 在 Kubernetes 中的佈署和管理,並提供稽核功能。從 PSP 到 OPA,Kubernetes 的安全機制不斷演進,提供更全面的保護。

啟用 PodSecurityPolicies

建立 PodSecurityPolicies

在 Kubernetes 中,PodSecurityPolicies(PSP)是一種重要的安全機制,用於控制 Pod 的建立和執行。為了啟用 PSP,首先需要建立相關的策略。

  1. 建立策略: 首先,需要定義並建立 PodSecurityPolicies。這涉及到編寫 YAML 檔案來描述所需的策略,並使用 kubectl create 命令將其應用到 Kubernetes 叢集中。

  2. 組態 API 伺服器: 一旦策略被建立,需要透過修改 /etc/kubernetes/manifests/kube-apiserver.yaml 檔案來啟用 PodSecurityPolicy 准入控制器。這涉及到將 --enable-admission-plugins 引數的值修改為包含 PodSecurityPolicy

修改 kube-apiserver.yaml

- --enable-admission-plugins=PodSecurityPolicy,NodeRestriction

修改後,API 伺服器 Pod 將會重啟,所有新的和更新的 Pod 物件將會透過 PodSecurityPolicy 准入控制器進行驗證。

應用 PodSecurityPolicies

  1. 重啟現有 Pod: 由於 PSP 是透過准入控制器強制執行的,任何沒有存取特權策略的 Pod 將繼續執行。要將策略應用於所有正在執行的 Pod,需要刪除它們:
kubectl delete pods --all-namespaces --all

這將刪除叢集中的所有 Pod,包括 etcd、網路元件等。叢集需要一些時間來重建這些 Pod。

  1. 驗證 PSP 應用: 一旦所有 Pod 都被重建,可以透過檢查 Pod 的註解來驗證是否應用了 PSP:
kubectl describe pod -l application=openunison-orchestra -n openunison

這將顯示 OpenUnison Pod 的詳細資訊,包括它所使用的 PSP。

除錯和生成 PSP

  1. 除錯 NGINX Ingress: 如果 NGINX Ingress 無法正常工作,可以透過檢查 ingress-nginx 名稱空間中的事件來找出原因:
kubectl get events -n ingress-nginx

錯誤訊息將指出 NGINX Ingress 無法建立,因為它無法透過 PSP 驗證。

  1. 檢查 Deployment 組態: 進一步檢查 NGINX Ingress 的 Deployment 組態,可以看到它試圖開啟 80 和 443 埠,並請求特權升級和 NET_BIND_SERVICE 能力。

Deployment 組態片段

ports:
- containerPort: 80
  hostPort: 80
  name: http
  protocol: TCP
- containerPort: 443
  hostPort: 443
  name: https
  protocol: TCP
securityContext:
  allowPrivilegeEscalation: true
  capabilities:
    add:
    - NET_BIND_SERVICE
    drop:
    - ALL
  runAsUser: 101

使用 kube-psp-advisor 生成 PSP

  1. 下載 kube-psp-advisor: 為了簡化 PSP 的建立過程,可以使用 Sysdig 的 kube-psp-advisor 工具。該工具可以檢查名稱空間中的 Pod 並生成推薦的 PSP 和 RBAC 組態。
./kubectl-advise-psp inspect --namespace=ingress-nginx

生成的 PSP 示例

apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
  creationTimestamp: null
  name: pod-security-policy-ingress-nginx-20200611232031
spec:
  defaultAddCapabilities:
  - NET_BIND_SERVICE
  fsGroup:
    rule: RunAsAny
  hostPorts:
  - max: 80
    min: 80
  - max: 443
    min: 443
  requiredDropCapabilities:
  - ALL
  runAsUser:
    ranges:
    - max: 101
      min: 101
    rule: MustRunAs
  seLinux:
    rule: RunAsAny
  supplementalGroups:
    rule: RunAsAny
  volumes:
  - secret
  1. 建立 PSP 檔案: 將生成的 PSP 儲存到檔案中,例如 psp-ingress.yaml

  2. 佈署 PSP: 使用 kubectl create 命令佈署 PSP。

  3. 建立 RBAC 繫結: 為 nginx-ingress-serviceaccount ServiceAccount 建立 Role 和 RoleBinding,以便它可以使用新的 PSP。

Role 和 RoleBinding 示例

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: nginx-ingress-psp
  namespace: ingress-nginx
rules:
- apiGroups:
  - policy
  resourceNames:
  - pod-security-policy-ingress-nginx-20200611232826
  resources:
  - podsecuritypolicies
  verbs:
  - use
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: nginx-ingress-psp-binding
  namespace: ingress-nginx
roleRef:
  name: nginx-ingress-psp
  kind: Role
subjects:
- kind: ServiceAccount
  name: nginx-ingress-serviceaccount
  namespace: ingress-nginx

透過這些步驟,可以成功地啟用和組態 PodSecurityPolicies,以提高 Kubernetes 叢集的安全性。

使用 Open Policy Agent 擴充套件安全性

到目前為止,我們已經介紹了 Kubernetes 的內建身份驗證和授權功能,這些功能有助於保護叢集的安全。雖然這些功能可以滿足大多數使用案例,但並不能涵蓋所有情況。一些 Kubernetes 無法處理的安全最佳實踐,例如預先授權容器登入檔和確保所有 Pod 物件都有資源請求,這些任務需要外部系統來完成,被稱為動態准入控制器。Open Policy Agent(OPA)及其 Kubernetes 原生子專案 GateKeeper 是處理這些使用案例最流行的工具之一。本章將詳細介紹 OPA 和 GateKeeper 的佈署、架構以及如何開發策略。

本章涵蓋以下主題:

  • 驗證 Webhook 簡介
  • 什麼是 OPA 以及它是如何工作的?
  • 使用 Rego 編寫策略

驗證 Webhook 簡介

在探討 OPA 之前,瞭解驗證 Webhook 的概念是非常重要的。驗證 Webhook 是 Kubernetes 中的一種機制,允許外部系統在資源建立或更新之前對其進行驗證。這使得叢集管理員可以實施自定義的安全策略和檢查,以確保資源符合特定的要求。

驗證 Webhook 的工作原理

驗證 Webhook 的工作流程如下:

  1. 當使用者建立或更新資源時,Kubernetes API 伺服器會將請求傳送到組態的 Webhook。
  2. Webhook 接收請求並對資源進行驗證。
  3. 如果資源符合要求,Webhook 傳回允許建立或更新的回應。
  4. 如果資源不符合要求,Webhook 傳回拒絕建立或更新的回應。

什麼是 OPA 以及它是如何工作的?

Open Policy Agent(OPA)是一個開源的、通用的策略引擎,可以與多種系統整合,包括 Kubernetes。OPA 提供了一種統一的方式來定義和執行策略,使得管理員可以輕鬆地在不同系統中實施一致的安全策略。

OPA 的架構

OPA 的架構主要包括以下幾個元件:

  • OPA 引擎:負責評估策略並做出允許或拒絕的決定。
  • Rego:OPA 使用的一種專門的策略語言,用於定義策略。

OPA 如何與 Kubernetes 整合

OPA 可以與 Kubernetes 整合,透過以下步驟:

  1. 將 OPA 佈署為 Kubernetes 中的一個 Pod。
  2. 組態 Kubernetes 使用 OPA 作為驗證 Webhook。
  3. 定義 Rego 策略並將其載入到 OPA 中。

使用 Rego 編寫策略

Rego 是 OPA 使用的策略語言,用於定義安全策略。編寫 Rego 策略需要了解 Rego 的語法和語義。

Rego 策略示例

以下是一個簡單的 Rego 策略示例,用於檢查 Pod 是否有資源請求:

package kubernetes.admission

deny[msg] {
    input.request.kind.kind == "Pod"
    not input.request.object.spec.containers[0].resources.requests.cpu
    msg := "CPU 資源請求是必需的"
}

這個策略檢查建立或更新的 Pod 是否有 CPU 資源請求。如果沒有,則傳回一個拒絕的回應。

內容解密:

這個 Rego 策略使用了 OPA 的內建 input 物件來存取請求的資料。首先,它檢查請求的種類別是否是 Pod。然後,它檢查 Pod 的第一個容器是否有 CPU 資源請求。如果沒有,它傳回一個錯誤訊息,指出 CPU 資源請求是必需的。

問題

  1. True or False:容器是「輕量級虛擬機器」。 A. True B. False

  2. 容器是否可以存取其主機的資源? A. 否,它是隔離的。 B. 如果標記為特權,則是。 C. 只有在明確授權的情況下才可以。 D. 有時。

  3. 攻擊者如何透過容器獲得對叢集的存取許可權? A. 容器應用程式中的錯誤可能導致遠端程式碼執行,從而用於突破脆弱的容器,然後用於取得 kubelet 的憑據。 B. 在一個名稱空間中具有建立容器的能力的使用者,可以建立一個掛載主機檔案系統的容器,以取得 kubelet 的憑據。 C. 以上兩種情況。

  4. PodSecurityPolicy 准入控制器如何確定要應用於 Pod 的策略? A. 透過讀取 Pod 定義中的註解。 B. 透過比較 Pod 請求的功能和透過 Pod 建立者和其 ServiceAccount 的聯合授權的策略。 C. 透過比較 Pod 請求的功能和其 ServiceAccount 授權的策略。 D. 透過比較 Pod 請求的功能和 Pod 建立者授權的策略。

OPA 工作流程

@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultTextAlignment center
skinparam rectangleBackgroundColor #F5F5F5
skinparam rectangleBorderColor #333333
skinparam arrowColor #333333

title OPA 工作流程

rectangle "傳送請求" as node1
rectangle "評估策略" as node2
rectangle "是" as node3
rectangle "否" as node4

node1 --> node2
node2 --> node3
node3 --> node4

@enduml

圖表翻譯: 此圖示展示了 OPA 在 Kubernetes 中的工作流程。Kubernetes API 伺服器將請求傳送到 OPA,OPA 評估策略後決定是否允許或拒絕該請求。

使用 Open Policy Agent 擴充套件安全性

動態准入控制器的介紹

Kubernetes 有兩種擴充套件方式:

  1. 建立自定義資源定義(CRD),以定義自有的物件和 API。
  2. 實作一個 webhook,監聽來自 API 伺服器的請求並回應必要的資訊。

從 Kubernetes 1.9 開始,webhook 可以被定義為動態准入控制器,而在 1.16 版本中,動態准入控制器 API 已達到一般可用(GA)狀態。協定非常直接:一旦為特定物件型別註冊了動態准入控制器,每當建立或編輯該型別的物件時,webhook 就會被呼叫並傳回 JSON,表示是否允許該操作。

請求和回應結構

提交給 webhook 的請求由多個部分組成:

  • 物件識別符號:resourcesubResource 屬性標識物件、API 和組。如果物件版本正在升級,則指定 requestKindrequestResourcerequestSubResource。此外,還提供 namespaceoperation 以瞭解物件的位置以及它是 CREATE、UPDATE、DELETE 還是 CONNECT 操作。
  • 提交者識別符號:userInfo 物件標識提交者的使用者和組。提交者和建立原始請求的使用者不總是相同的。
  • 物件:object 表示提交的物件的 JSON,而 oldObject 表示如果是更新操作時被替換的內容。最後,options 指定請求的其他選項。

webhook 的回應只有兩個屬性:原始請求的 uidallowed,後者可以是 true 或 false。

OPA 簡介及其工作原理

OPA(Open Policy Agent)是一個輕量級的授權引擎,非常適合在 Kubernetes 中使用。OPA 最初並非為 Kubernetes 設計,但現在已在 Kubernetes 社群中得到廣泛應用。

OPA 架構

OPA 由三個元件組成:HTTP 監聽器、策略引擎和資料函式庫。 此架構使得 OPA 成為一個高度可擴充套件的授權微服務。然而,每個 OPA 例項都需要獨立維護,並與授權資料保持同步。

在 Kubernetes 中使用 OPA

在 Kubernetes 中,OPA 使用一個名為 kube-mgmt 的 sidecar 來填充其資料函式庫。kube-mgmt 對想要匯入 OPA 的物件設定監視,並在物件建立、刪除或更改時更新 OPA 例項中的資料。

Rego:OPA 的策略語言

Rego 是 OPA 的策略評估語言,而不是通用程式語言。這種設計使得 Rego 在評估策略時非常高效。

示例:驗證容器映象倉函式庫

假設您想檢查 Pod 中的容器映象是否來自允許的倉函式庫列表,用 Java 編寫的程式碼可能如下所示:

public boolean validRegistries(List<Container> containers, List<String> allowedRegistries) {
    for (Container c : containers) {
        boolean imagesFromApprovedRegistries = false;
        for (String allowedRegistry : allowedRegistries) {
            // 邏輯判斷
        }
    }
}

內容解密:

上述 Java 程式碼片段用於檢查一系列容器是否使用了允許的映象倉函式庫。它遍歷每個容器,並檢查其映象倉函式庫是否在允許的倉函式庫列表中。這種邏輯在 Rego 中可以更簡潔地表達,利用 Rego 的內建功能來評估策略。

圖表說明

@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultTextAlignment center
skinparam rectangleBackgroundColor #F5F5F5
skinparam rectangleBorderColor #333333
skinparam arrowColor #333333

title 圖表說明

rectangle "請求" as node1
rectangle "准入控制" as node2
rectangle "呼叫" as node3
rectangle "評估策略" as node4
rectangle "傳回結果" as node5
rectangle "准入決定" as node6
rectangle "最終結果" as node7

node1 --> node2
node2 --> node3
node3 --> node4
node4 --> node5
node5 --> node6
node6 --> node7

@enduml

圖表翻譯: 此圖示展示了客戶端請求透過 Kubernetes API 伺服器,並由動態准入控制器呼叫 OPA webhook 進行策略評估的流程。OPA webhook 使用 Rego 策略引擎評估請求,最終將結果傳回給 Kubernetes API 伺服器,以決定是否允許該請求。

使用Open Policy Agent擴充套件安全性

OPA與Rego簡介

Open Policy Agent(OPA)是一種通用策略引擎,可用於多種環境,包括Kubernetes。OPA使用一種名為Rego的專用語言來編寫策略。Rego不同於大多數程式語言,它採用宣告式語法,能夠以更簡潔的方式表達複雜的策略邏輯。

OPA與Kubernetes的整合

在Kubernetes環境中,OPA可以透過GateKeeper進行整合。GateKeeper提供了一種Kubernetes原生的體驗,使得OPA的佈署和管理更加便捷。GateKeeper不僅能夠驗證資源是否符合策略,還能夠對現有資源進行稽核,以檢測違反策略的情況。

使用Rego編寫策略

Rego是一種專為編寫策略而設計的語言。它與傳統的程式語言有著顯著的不同。傳統的授權程式碼通常預設為拒絕存取,然後在滿足特定條件時才允許存取。相反,Rego預設為允許所有存取,除非滿足特定的條件。

Rego的基本語法

Rego沒有明確的if/then/else控制陳述式。當一行Rego程式碼用於做出決策時,如果該行程式碼為false,則停止執行。這種語法使得Rego程式碼更加簡潔。

invalidRegistry {
  ok_images = [image | startswith(input_images[j], input.parameters.registries[_]) ; image = input_images[j] ]
  count(ok_images) != count(input_images)
}

程式碼解密:

  1. invalidRegistry是一個規則名稱,用於檢查映象是否來自受信任的登入檔。
  2. ok_images是一個集合,包含了所有來自受信任登入檔的映象。
  3. count(ok_images) != count(input_images)檢查是否存在任何映象不是來自受信任的登入檔。如果存在,則invalidRegistry規則為true。

GateKeeper的佈署

GateKeeper的佈署可以透過以下命令完成:

$ kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper/master/deploy/gatekeeper.yaml

自動化測試框架

OPA提供了一個內建的自動化測試框架,用於測試策略。測試檔案應與策略檔案在同一目錄下,並以_test結尾。例如,對於mypolicies.rego,測試檔案應命名為mypolicies_test.rego。執行opa test命令即可執行測試。

Rego與其他語言的比較

Rego與其他程式語言的主要區別在於其宣告式語法和預設允許所有存取的特性。下面是一個Java示例,與前面的Rego程式碼相對應:

if (!image.startsWith("myregistry.lan/")) {
  throw new Exception("image " + image + " comes from untrusted registry");
}

程式碼解密:

  1. 檢查image是否以myregistry.lan/開頭。
  2. 如果不是,則丟擲一個異常,指出映象來自不受信任的登入檔。