本文已超過一年。較舊的文章可能包含過時的內容。檢查頁面中的資訊自發布以來是否已變得不正確。
Kubernetes 驗證許可政策:實務範例
准入控制是 Kubernetes 控制平面的重要組成部分,多個內部功能取決於在 API 物件提交到伺服器時批准或更改它的能力。對於管理員來說,能夠定義關於哪些物件可以被准入叢集的業務邏輯或策略也很有用。為了更好地支援該用例,Kubernetes 在 v1.7 中引入了外部准入控制。
除了無數自訂的內部實作之外,許多開源專案和商業解決方案都使用使用者指定的策略實作了准入控制器,包括 Kyverno 和 Open Policy Agent 的 Gatekeeper。
雖然用於策略的准入控制器已經被採用,但它們的廣泛使用存在障礙。Webhook 基礎設施必須作為生產服務進行維護,這需要付出一切努力。准入控制 webhook 的故障情況必須是關閉(降低叢集的可用性)或打開(否定該功能用於策略執行的用途)。網路躍點和評估時間使准入控制成為處理延遲的一個顯著組成部分,例如,在「無伺服器」環境中,Pod 被啟動以響應網路請求時。
驗證准入策略和通用表達式語言
Kubernetes 的 1.26 版本在 alpha 中引入了一個折衷解決方案。驗證准入策略是一種宣告式的、進程內的准入 webhook 替代方案。它們使用 通用表達式語言 (CEL) 來宣告驗證規則。
CEL 由 Google 為安全和策略用例開發,基於 Firebase 實時資料庫的經驗。它的設計使其可以安全地嵌入到應用程式中並在微秒內執行,計算和記憶體影響有限。CRD 的驗證規則在 v1.23 中將 CEL 引入了 Kubernetes 生態系統,當時有人指出,該語言將適用於通過准入控制進行更通用的驗證實作。
讓 CEL 發揮作用 - 一個實際範例
Kubescape 是一個 CNCF 專案,已成為使用者提高 Kubernetes 叢集安全態勢和驗證其合規性的最流行方式之一。它的 控制 — 針對 API 物件的測試組 — 內建於 Rego,Open Policy Agent 的策略語言。
Rego 因其複雜性而聞名,這主要是因為它是一種宣告式查詢語言(如 SQL)。它 被考慮用於 Kubernetes,但它沒有提供與 CEL 相同的沙箱約束。
該專案的一個常見功能請求是能夠根據 Kubescape 的發現和輸出實作策略。例如,在掃描 Pod 以查找 已知的雲憑證檔案路徑後,使用者希望能夠強制執行策略,即根本不應准入這些 Pod。Kubescape 團隊認為這將是嘗試將我們現有的控制移植到 CEL 並將其應用為准入策略的絕佳機會。
向我展示策略
我們沒有花費太多時間來轉換我們的許多控制並構建一個 驗證准入策略庫。讓我們看一個範例。
Kubescape 的 控制 C-0017 涵蓋了容器需要具有不可變(唯讀)根檔案系統的要求。根據 NSA Kubernetes 強化指南,這是一種最佳實務,但目前並未作為任何 Pod 安全標準的一部分要求。
以下是我們如何在 CEL 中實作它
apiVersion: admissionregistration.k8s.io/v1alpha1
kind: ValidatingAdmissionPolicy
metadata:
name: "kubescape-c-0017-deny-resources-with-mutable-container-filesystem"
spec:
failurePolicy: Fail
matchConstraints:
resourceRules:
- apiGroups: [""]
apiVersions: ["v1"]
operations: ["CREATE", "UPDATE"]
resources: ["pods"]
- apiGroups: ["apps"]
apiVersions: ["v1"]
operations: ["CREATE", "UPDATE"]
resources: ["deployments","replicasets","daemonsets","statefulsets"]
- apiGroups: ["batch"]
apiVersions: ["v1"]
operations: ["CREATE", "UPDATE"]
resources: ["jobs","cronjobs"]
validations:
- expression: "object.kind != 'Pod' || object.spec.containers.all(container, has(container.securityContext) && has(container.securityContext.readOnlyRootFilesystem) && container.securityContext.readOnlyRootFilesystem == true)"
message: "Pods having containers with mutable filesystem not allowed! (see more at https://hub.armosec.io/docs/c-0017)"
- expression: "['Deployment','ReplicaSet','DaemonSet','StatefulSet','Job'].all(kind, object.kind != kind) || object.spec.template.spec.containers.all(container, has(container.securityContext) && has(container.securityContext.readOnlyRootFilesystem) && container.securityContext.readOnlyRootFilesystem == true)"
message: "Workloads having containers with mutable filesystem not allowed! (see more at https://hub.armosec.io/docs/c-0017)"
- expression: "object.kind != 'CronJob' || object.spec.jobTemplate.spec.template.spec.containers.all(container, has(container.securityContext) && has(container.securityContext.readOnlyRootFilesystem) && container.securityContext.readOnlyRootFilesystem == true)"
message: "CronJob having containers with mutable filesystem not allowed! (see more at https://hub.armosec.io/docs/c-0017)"
為三個可能的 API 群組提供了匹配約束:Pod 的 core/v1
群組、apps/v1
工作負載控制器和 batch/v1
工作控制器。
注意
matchConstraints
將為您將 API 物件轉換為匹配的版本。例如,如果 API 請求是針對 apps/v1beta1
,並且您在 matchConstraints 中匹配 apps/v1
,則 API 請求將從 apps/v1beta1
轉換為 apps/v1
,然後進行驗證。這具有有用的特性,可以使驗證規則安全地防止引入新版本的 API,否則會允許 API 請求通過使用新引入的版本來偷偷繞過驗證規則。validations
包括物件的 CEL 規則。有三個不同的表達式,用於處理 Pod spec
可能位於物件的根目錄(裸 Pod)、template
下(工作負載控制器或 Job),或 jobTemplate
下(CronJob)的事實。
如果任何 spec
沒有將 readOnlyRootFilesystem
設置為 true,則物件將不會被准入。
注意
在我們的初始版本中,我們已將三個表達式分組到同一個策略物件中。這意味著它們可以原子地啟用和停用,因此不會有使用者因啟用一個 API 群組的策略而未啟用其他 API 群組的策略而意外留下合規性差距的機會。將它們分解為單獨的策略將使我們能夠訪問針對 1.27 版本的改進,包括類型檢查。我們正在與 SIG API Machinery 討論如何在 API 達到v1
之前最好地解決這個問題。在您的叢集中使用 CEL 庫
策略作為 Kubernetes 物件提供,然後通過 選擇器綁定到某些資源。
Minikube 是一種快速簡便的方式來安裝和配置 Kubernetes 叢集以進行測試。要安裝啟用 ValidatingAdmissionPolicy
功能閘道的 Kubernetes v1.26
minikube start --kubernetes-version=1.26.1 --extra-config=apiserver.runtime-config=admissionregistration.k8s.io/v1alpha1 --feature-gates='ValidatingAdmissionPolicy=true'
要在您的叢集中安裝策略
# Install configuration CRD
kubectl apply -f https://github.com/kubescape/cel-admission-library/releases/latest/download/policy-configuration-definition.yaml
# Install basic configuration
kubectl apply -f https://github.com/kubescape/cel-admission-library/releases/latest/download/basic-control-configuration.yaml
# Install policies
kubectl apply -f https://github.com/kubescape/cel-admission-library/releases/latest/download/kubescape-validating-admission-policies.yaml
要將策略應用於物件,請創建 ValidatingAdmissionPolicyBinding
資源。讓我們將上述 Kubescape C-0017 控制應用於任何具有標籤 policy=enforced
的命名空間
# Create a binding
kubectl apply -f - <<EOT
apiVersion: admissionregistration.k8s.io/v1alpha1
kind: ValidatingAdmissionPolicyBinding
metadata:
name: c0017-binding
spec:
policyName: kubescape-c-0017-deny-mutable-container-filesystem
matchResources:
namespaceSelector:
matchLabels:
policy: enforced
EOT
# Create a namespace for running the example
kubectl create namespace policy-example
kubectl label namespace policy-example 'policy=enforced'
現在,如果您嘗試創建一個未指定 readOnlyRootFilesystem
的物件,則不會創建它。
# The next line should fail
kubectl -n policy-example run nginx --image=nginx --restart=Never
輸出顯示我們的錯誤
The pods "nginx" is invalid: : ValidatingAdmissionPolicy 'kubescape-c-0017-deny-mutable-container-filesystem' with binding 'c0017-binding' denied request: Pods having containers with mutable filesystem not allowed! (see more at https://hub.armosec.io/docs/c-0017)
組態
策略物件可以包含組態,該組態在不同的物件中提供。許多 Kubescape 控制都需要組態:要要求的標籤、要允許或拒絕的功能、允許從中部署容器的登錄檔等。這些控制的預設值在 ControlConfiguration 物件中定義。
要使用此組態物件,或您自己的相同格式的物件,請將 paramRef.name
值添加到您的綁定物件
apiVersion: admissionregistration.k8s.io/v1alpha1
kind: ValidatingAdmissionPolicyBinding
metadata:
name: c0001-binding
spec:
policyName: kubescape-c-0001-deny-forbidden-container-registries
paramRef:
name: basic-control-configuration
matchResources:
namespaceSelector:
matchLabels:
policy: enforced
總結
在大多數情況下,將我們的控制轉換為 CEL 很簡單。我們無法移植整個 Kubescape 庫,因為某些控制檢查 Kubernetes 叢集之外的事物,而某些控制需要准入請求物件中不可用的數據。總體而言,我們很高興將此庫貢獻給 Kubernetes 社群,並將繼續為 Kubescape 和 Kubernetes 使用者開發它。我們希望它變得有用,無論是作為您自己使用的東西,還是作為您編寫自己的策略的範例。
至於驗證准入策略功能本身,我們非常興奮地看到 Kubernetes 中引入了這種原生功能。我們期待看到它轉變為 Beta,然後是 GA,希望在今年年底之前。重要的是要注意,此功能目前處於 Alpha 階段,這意味著這是使用 Minikube 等環境進行試用並進行試駕的絕佳機會。但是,它尚未被視為可生產且穩定,並且不會在大多數託管 Kubernetes 環境中啟用。在底層功能變得穩定之前,我們不會建議 Kubescape 使用者在生產環境中使用這些策略。請關注 KEP,當然還有這個部落格,以獲取最終的發布公告。