Kubernetes 原生 Pod 安全策略機制即將棄用,Open Policy Agent (OPA) 和 GateKeeper 成為更靈活的安全策略方案。Rego 策略語言允許定義細緻的規則,例如強制 Pod 記憶體資源請求。GateKeeper 快取機制能有效提升策略評估效率,減少 API 伺服器負載。此外,Falco 與 EFK 堆積疊的整合提供更全面的容器安全稽核和事件分析能力,彌補 Kubernetes 原生稽核功能的不足。透過這些工具,可以更有效地控管叢集資源,提升安全性。
使用開放策略代理(Open Policy Agent)擴充套件安全性
在設計和實施策略時,詳細程度至關重要。為了確保策略的完整性,使用現有的、經過測試的策略是一個好方法。GateKeeper 專案在其 GitHub 儲存函式庫中維護了多個預先測試的策略函式庫。在嘗試建立自己的策略之前,應先檢查是否已有現成的策略可用。
Rego 與策略評估
本文概述了 Rego 的基本原理及其在策略評估中的運作方式。雖然沒有涵蓋所有內容,但為進一步查閱 Rego 檔案提供了良好的參考起點。接下來,我們將學習如何建立依賴於請求以外資料的策略,例如叢集中的其他物件。
強制記憶體限制
到目前為止,本章節中建立的策略都是自包含的。在檢查映像是否來自預授權的登入檔時,所需的資料僅來自策略和容器。然而,這通常不足以做出策略決策。在本文中,我們將建立一個依賴於叢集中其他物件的策略。
使用案例
在向 API 伺服器提交任何 Pod 時,至少應包含記憶體需求。然而,在某些名稱空間中,這並不那麼有意義。例如,kube-system 名稱空間中的許多容器沒有 CPU 和記憶體資源請求。
有多種方法可以處理這種情況。一種方法是佈署約束範本,並將其應用於每個需要強制記憶體資源請求的名稱空間。這可能導致重複的物件,或需要明確更新策略以將其應用於特定的名稱空間。另一種方法是向名稱空間新增標籤,讓 OPA 知道它需要所有 Pod 物件具有記憶體資源請求。由於 Kubernetes 已經具有用於管理記憶體的 ResourceQuota 物件,因此我們也可以確定名稱空間是否具有 ResourceQuota,如果有,則知道應該有記憶體請求。
建立強制記憶體請求的策略
我們的下一個範例將建立一個策略,規定在具有 ResourceQuota 的名稱空間中建立的任何 Pod 都必須具有記憶體資源請求。該策略本身應該很簡單。偽程式碼如下所示:
if (hasResourceQuota(input.review.object.metadata.namespace) &&
containers.resource.requests.memory == null) {
generate error;
}
困難的部分是瞭解名稱空間是否具有 ResourceQuota。
啟用 GateKeeper 快取
GateKeeper 快取透過在 gatekeeper-system 名稱空間中建立 Config 物件來啟用。將以下組態新增到叢集中:
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: "ResourceQuota"
這將開始在 GateKeeper 的內部 OPA 資料函式庫中複製 Namespace 和 ResourceQuota 物件。
模擬測試資料
為了自動化策略測試,我們需要建立測試資料。在前面的範例中,我們使用注入 input 變數的資料。快取資料儲存在 data 變數中。具體來說,為了存取我們的資源配額,我們需要存取 data.inventory.namespace["ns-with-quota"]["v1"]["ResourceQuota"]["memory-quota"]。這是從 Rego 中查詢 GateKeeper 中資料的標準方式。
{
"inventory": {
"namespace": {
"ns-with-no-quota": {},
"ns-with-quota": {
"v1": {
"ResourceQuota": {
"memory-quota": {
"kind": "ResourceQuota",
"apiVersion": "v1",
"metadata": {
"name": "memory-quota",
"namespace": "ns-with-quota"
},
"spec": {
"hard": {
"requests.memory": "1G",
"limits.memory": "1G"
}
}
}
}
}
}
}
}
}
詳細解說
上述 JSON 資料結構模擬了 GateKeeper 快取中的資料,用於測試我們的策略。透過建立 data 物件,我們可以注入模擬版本的資料,從而在不將程式碼佈署到叢集中的情況下測試我們的策略。
重點整理
- 使用現有的、經過測試的策略可以提高策略的完整性。
- Rego 是用於定義和評估策略的語言。
- GateKeeper 提供了一種機制來快取叢集中的資料,以便在策略評估中使用。
- 透過模擬測試資料,可以自動化測試我們的策略。
策略開發最佳實踐
- 重用現有策略:在開發新策略之前,先檢查是否已有現成的策略可用。
- 詳細設計和測試:確保策略設計周密,並進行充分的測試。
- 利用 GateKeeper 快取:使用 GateKeeper 快取機制來存取叢集中的資料。
- 模擬測試資料:透過模擬測試資料來自動化測試我們的策略。
使用 Open Policy Agent 擴充套件安全性
建置與佈署策略
如同之前的操作,在撰寫策略之前,我們已經先寫好了測試案例。接下來,我們將檢視我們的策略:
package k8senforcememoryrequests
violation[{"msg": msg, "details": {}}] {
invalidMemoryRequests
msg := "No memory requests specified"
}
invalidMemoryRequests {
data.inventory.namespace[input.review.object.metadata.namespace]["v1"]["ResourceQuota"]
containers := input.review.object.spec.containers
ok_containers = [ok_container |
containers[j].resources.requests.memory ;
ok_container = containers[j]
]
count(containers) != count(ok_containers)
}
內容解密:
package k8senforcememoryrequests:定義了 Rego 策略的套件名稱,用於識別和組織相關的規則。violation規則:這是 GateKeeper 的標準報告規則,用於輸出違規訊息。當invalidMemoryRequests成立時,會設定msg為 “No memory requests specified”,並將其包含在違規訊息中。invalidMemoryRequests規則:檢查 Pod 是否在具有ResourceQuota的名稱空間中執行,並且其容器是否指定了記憶體請求。data.inventory.namespace[input.review.object.metadata.namespace]["v1"]["ResourceQuota"]:檢查特定名稱空間中是否存在ResourceQuota物件。如果不存在,則規則失敗並離開。containers := input.review.object.spec.containers:載入 Pod 的所有容器。ok_containers = [ok_container | containers[j].resources.requests.memory ; ok_container = containers[j] ]:使用列表推導式建立一個只包含已指定記憶體請求的容器的列表。count(containers) != count(ok_containers):比較總容器數量和已符合記憶體請求設定的容器數量。如果數量不相等,表示至少有一個容器未指定記憶體請求,規則成功。
要佈署此策略,請將 chapter11/enforce-memory-request/yaml/gatekeeper-policy-template.yaml 和 chapter11/enforce-memory-request/yaml/gatekeeper-policy.yaml 新增到您的叢集中。
使用 OPA 強制實施 Pod 安全策略
在 Kubernetes 中,現有的 Pod 安全策略實作將不會進入 “GA” 狀態。使用 OPA 和 GateKeeper 可以在 OPA 中強制實施相同的策略,而不是在 API 伺服器上。GateKeeper 的策略釋出於 https://github.com/open-policy-agent/gatekeeper/tree/master/library/pod-security-policy。
主要差異
宣告式定義:使用 GateKeeper,您必須在 Pod 定義中宣告所有內容,以便 GateKeeper 有東西可以稽核。這與 Kubernetes 的 Pod 安全策略不同,後者會改變 Pod 定義以符合策略。
策略指派:GateKeeper 使用名稱空間和標籤選擇器來匹配策略,而 Kubernetes 標準實作則使用 RBAC 和 Pod 的
serviceAccount及請求的功能來決定使用哪個策略。策略分割:GateKeeper 的策略函式庫被分割成多個物件。要套用一個強制執行非特權容器在特定使用者範圍內執行的策略,您需要兩個單獨的策略約束實作和兩個單獨的約束。
使用Falco與EFK進行稽核
在大多數執行Kubernetes叢集的環境中,您需要有一個稽核系統來監控叢集的執行狀態。Kubernetes本身具備一些稽核功能,但往往過於有限,無法滿足企業對完整稽核軌跡的需求。幸運的是,有許多第三方日誌系統可供選擇,例如Splunk、Datadog等付費系統,以及EFK(Elasticsearch、Fluentd、Kibana)堆積疊等開源系統。
探索稽核
Kubernetes的原生稽核功能主要集中在API存取事件上,但這並不足以滿足大多數企業的需求。企業通常需要擴充套件或自定義稽核目標,以涵蓋更廣泛的事件型別。Falco是一個開源專案,可以為您的Pod提供增強的稽核功能,記錄API伺服器未記錄的事件。
為什麼需要Falco?
當使用者在Pod中執行命令時,例如使用kubectl exec -it <pod name> bash,這會向API伺服器傳送請求,但後續在Pod中執行的命令不會被記錄。這對於企業來說是一個很大的稽核漏洞,因為這可能導致惡意行為未被檢測到。
引入Falco
Falco是一個開源的容器安全工具,可以檢測並報警異常行為。它可以監控系統呼叫,並根據預定義的規則進行報警。Falco可以與EFK堆積疊整合,提供強大的日誌收集和分析功能。
Falco的組態檔案
Falco的組態檔案定義了要監控的事件和規則。您可以自定義這些檔案以滿足特定的需求。
佈署Falco
要佈署Falco,您需要在Kubernetes叢集中安裝Falco的DaemonSet。DaemonSet將在每個節點上執行一個Falco例項。
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: falco
spec:
selector:
matchLabels:
name: falco
template:
metadata:
labels:
name: falco
spec:
containers:
- name: falco
image: falcosecurity/falco:latest
securityContext:
privileged: true
Falco核心模組
Falco需要一個核心模組來監控系統呼叫。您可以選擇使用核心模組或eBPF探針。
使用EFK堆積疊進行日誌收集和分析
EFK堆積疊是一個強大的日誌收集和分析工具。它包括Elasticsearch(用於儲存和索引日誌)、Fluentd(用於收集和轉發日誌)和Kibana(用於視覺化日誌資料)。
佈署EFK堆積疊
要佈署EFK堆積疊,您需要在Kubernetes叢集中安裝Elasticsearch、Fluentd和Kibana。
apiVersion: apps/v1
kind: Deployment
metadata:
name: elasticsearch
spec:
replicas: 1
selector:
matchLabels:
app: elasticsearch
template:
metadata:
labels:
app: elasticsearch
spec:
containers:
- name: elasticsearch
image: docker.elastic.co/elasticsearch/elasticsearch:7.10.2
重點回顧
- Falco是一個開源的容器安全工具,可以檢測並報警異常行為。
- EFK堆積疊是一個強大的日誌收集和分析工具。
- 將Falco與EFK堆積疊整合,可以提供全面的稽核功能。
問題與解答
- OPA和GateKeeper是相同的東西嗎?
- A. 是
- B. 否
答案:B. 否
- Rego程式碼在GateKeeper中如何儲存?
- A. 儲存為ConfigMap物件。
- B. 需要掛載到Pod中。
- C. 需要儲存為Secret物件。
- D. 儲存為ConstraintTemplate。
答案:D. 儲存為ConstraintTemplate
內容解密:
Rego是一種用於定義策略的語言,GateKeeper使用Rego來定義和管理策略。Rego程式碼儲存在ConstraintTemplate中,這些範本定義了策略的結構和規則。
- 如何測試Rego策略?
- A. 在生產環境中測試。
- B. 使用內建於OPA的自動化框架。
- C. 首先編譯成Web Assembly。
答案:B. 使用內建於OPA的自動化框架
內容解密:
OPA提供了內建的測試框架,用於測試Rego策略。可以使用opa test命令執行測試,並使用-v選項檢視詳細的執行跟蹤。
- 在Rego中如何寫一個for迴圈?
- A. 不需要寫,Rego會自動識別迭代步驟。
- B. 使用
for all語法。 - C. 初始化迴圈計數器。
- D. Rego中沒有迴圈。
答案:B. 使用for all語法
內容解密:
Rego使用for all語法來實作迭代。這種語法允許您對集合中的每個元素進行操作。
- 如何除錯Rego策略?
- A. 使用IDE附加到GateKeeper容器。
- B. 在生產環境中除錯。
- C. 在程式碼中新增trace函式,並使用
opa test -v檢視執行跟蹤。 - D. 使用
System.out陳述式。
答案:C. 在程式碼中新增trace函式,並使用opa test -v檢視執行跟蹤
內容解密:
在Rego程式碼中新增trace函式,可以輸出除錯資訊。使用opa test -v命令執行測試,可以檢視詳細的執行跟蹤,從而幫助除錯Rego策略。