翻譯:小君君

技術校對:星空下的文仔、bot

在項目中, Kubernetes 集羣會對 Kubernetes APIServer 的每個請求都進行身份驗證和授權管理。在此過程中,授權管理通常由 RBAC 授權模塊來實現,但開發者也可以選擇其他組件,如 Open Policy Agent(OPA)。

本文從使用目的、設計方式以及示例演示闡述瞭如何利用 Webhook 授權模塊使 OPA 實現高級授權策略。

使用動機

在一些項目中,我們希望為用戶提供類似集羣管理員的訪問許可權。但為了確保基線的安全性和穩定性,我們不希望授予用戶完整的集羣管理員許可權。例如:

  • 我們允許用戶完全訪問除kube-system之外的所有 namespace,因為我們的基礎設施(例如監視和日誌記錄)部署在kube-system中;
  • 我們希望強制執行 PodSecurityPolicy,不允許用戶以root的身份運行容器,也不允許用戶直接掛載hostPath卷。

面對這些要求,一種解決方案是通過 Kubernetes RBAC 和一個自定義操作符實現授權。其基本思想是讓所有必要的許可權通過 RBAC RoleBindings 進行授予綁定。並且,除了kube-system(通過 operator)之外,我們為每個 namespace 的客戶提供了 ClusterRole admin。每當我們發現某些東西不能像預期那樣工作時,我們就會通過每個 namespace 角色或 ClusterRole 添加其他許可權。

但是,這種方式會出現很多針對特定用例的單獨規則。從長遠發展角度來看,這些規則無法得到很好的維護。特別是在用戶羣不斷增長的情況下,只要有人檢測到與配置不匹配的邊緣情況,調整角色不太可行。

綜上所述,我們不能選擇基於白名單的配置授權,而是需要切換到基於黑名單的模型。因為,我們真正想要的是為客戶提供集羣管理員訪問許可權,並限制某些特定許可權。

基於白名單與黑名單的授權

關於授權,絕大多數要求可以通過 Roles 和 RoleBindings 簡單地使用 RBAC 授權模塊來實現 [1]。但 RBAC 在設計上僅限於白名單。即對於每個請求,它會選擇檢查其中的一個 Roles 和 RoleBindings 是否適用,然後批准請求。

請求只有在沒有匹配項時才會被拒絕,雖然聽起來限制不大,但一些特定用例需要更大的靈活性。例如:

  • 當用戶想在除kube-system之外的所有 namespace 中創建/更新/刪除 Pod 時,通過 RBAC 實現此目的的唯一方法是在每個 namespace 的基礎上分配許可權。例如,我們可以部署 ClusterRole 和每個 namespace 的 RoleBinding。如果 namespace 隨時間而變化,則必須手動部署此 RoleBindings 或為它運行 operator;
  • 當 Kubernetes 集羣提供預安裝的 StorageClass 時,用戶可能會想要擁有創建/更新/刪除自定義 StorageClass 的許可權。但他不應該有修改預安裝 StorageClass 的許可權。如果你想利用 RBAC 來實現,則用戶必須有權創建 StorageClass,並且一旦創建 StorageClass,就必須分配其他許可權以更新和刪除此 StorageClass。

如果你有很多這樣的用例,你就要通過運營商來實現很多自定義的邏輯,但是你需要知道這些用例可能不會被擴展。因為這樣做就會有很多的運營商和隨附的 RBAC 角色,我們將很難控制用戶實際擁有的權利。下面,我們將展示如何通過 OPA 輕鬆實現上述兩種情況。

Webhook 授權模塊與 ValidatingWebhook & MutatingWebhook

除了本文探討的情況,一些高級用例也可以通過 Dynamic Admission Control 實現,如 ValidatingWebhook 或 MutatingWebhook。這裡為大家推薦兩篇關於如何使用 OPA 的博客:Policy Enabled Kubernetes with Open Policy Agent [2]以及 Kubernetes Compliance with Open Policy Agent [3]。

動態准入控制具有以下限制:僅在 Kubernetes 資源上調用 Webhook 來創建、更新和刪除事件。因此,它們不可能拒絕獲取的請求。但與 Webhook 授權模塊相比,它們也具有優勢,因為它們可以根據 Kubernetes 資源的內容拒絕請求。這些是 Webhook 授權模塊無法訪問的信息。

作為參考,Webhook 授權模塊由 SubjectAccessReviews 決定,而 ValidatingWebhook 和 MutatingWebhook 則由 AdmissionReviews 決定。在實踐中,我們通過授權模塊和 MutatingWebhook 來集成 OPA。

設計

本節概述了 Kubernetes 如何與 OPA 集成。由於 OPA 本身不能實現 Kubernetes 所需的 REST 介面,所以 Kubernetes Policy Controller 將 Kubernetes SubjectAccessReviews 和 AdmissionReviews 轉換為 OPA 查詢。

對於 Kubernetes API 伺服器收到的每個請求,執行以下序列:

  • 請求已通過身份驗證;
  • 基於通過認證提取的用戶信息,授權請求:
  • 調用 Webhook。在我們的例子中,Webhook 可以拒絕請求或將其轉為發給 RBAC。Kubernetes Webhook 也可以允許請求,但這在 Kubernetes Policy Controller 中無法實現;
  • 執行 RBAC 模塊。如果 RBAC 不允許該請求,則拒絕該請求;
  • 如果請求導致持久性發生變化,例如創建/更新/刪除資源,則執行 Admission Controllers(MutatingWebhook 只是其中之一)。

因此,根據我們想要拒絕的具體內容,我們可以實施授權或許可 OPA 策略。有關如何配置此方案的更多信息,請參見 open-policy-agent / kubernetes-policy-controller(授權方案[4])。

實現

本節將說明如何使用 OPA 實現上述用例。除 kube-system 之外,為每個 namespace 創建/更新/刪除 Pod。

它的基本思想是通過 RBAC 在集羣範圍內授予 Pod 的創建/更新/刪除許可權,然後使用 OPA 策略拒絕訪問 kube-system 中的 Pod。首先,我們授予user組創建/更新/刪除 Pod 的許可權:

kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: pods
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["create", "update", "delete"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: user-pods
subjects:
- kind: Group
name: user
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: pods
apiGroup: rbac.authorization.k8s.io

現在,允許user組中每個用戶在集羣範圍內創建/更新/刪除 Pod。如有需要通過 OPA 限制這些許可權,請部署以下策略:

package authorization
import data.k8s.matches
deny[{
"id": "pods-kube-system",
"resource": {
"kind": kind,
"namespace": namespace,
"name": name,
}, "resolution":
{
"message": "Yourre not allowed to create/update/delete pods in kube-system"

},
}]
{
matches[[kind, namespace, name, resource]]
not re_match("^(system:kube-controller-manager|system:kube-scheduler)$",
resource.spec.user)
resource.spec.resourceAttributes.namespace = "kube-system"
resource.spec.resourceAttributes.resource = "pods"
re_match("^(create|update|delete|deletecollections)$",
resource.spec.resourceAttributes.verb)
}

注意

排除system:kube-controller-managersystem:kube-scheduler,因為 Kubernetes 控制管理器和調度程序都必須能夠訪問 Pod。

resource.spec.resourceAttributes.resource ="pods" 如果刪除,我們就可以限制對kube-system中所有 namespace 資源的訪問。

OPA 使我們為所有策略編寫單元測試變得非常容易。有關更多信息,請參閱如何測試策略[5]。

在特定 StorageClass 上執行創建/更新/刪除

在此示例中,我們要授予用戶對除ceph之外的所有 StorageClass 創建/更新/刪除許可權。與第一個示例一樣,我們必須通過 RBAC 授予用戶訪問許可權:

kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: storageclasses
rules:
- apiGroups: ["storage.k8s.io"]
resources: ["storageclasses"]
verbs: ["create", "update", "delete"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: user-storageclasses
subjects:
- kind: Group
name: user
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: storageclasses
apiGroup: rbac.authorization.k8s.io

現在我們需要拒絕通過 OPA 訪問 StorageClass 的ceph,部署以下策略:

package authorization
import data.k8s.matches
deny[{
"id": "storageclasses",
"resource": {
"kind": kind,
"namespace": namespace,
"name": name,
},
"resolution": {"message": "Yourre not allowed to create/update/delete the StorageClassceph"},
}] {
matches[[kind, namespace, name, resource]]
resource.spec.resourceAttributes.resource = "storageclasses"
resource.spec.resourceAttributes.name = "ceph"
re_match("^(create|update|delete|deletecollections)$",
resource.spec.resourceAttributes.verb)
}

你可以通過以下的方式進行策略的單元測試:

package authorization
test_deny_update_storageclass_ceph {
deny[{"id": id, "resource":
{
"kind": "storageclasses", "namespace": "", "name": "ceph"},
"resolution": resolution
}]
with data.kubernetes.storageclasses[""].ceph as
{ "kind": "SubjectAccessReview",
"apiVersion": "authorization.k8s.io/v1beta1",
"spec":
{ "resourceAttributes":
{ "verb": "update",
"version": "v1",
"resource": "storageclasses",
"name": "ceph",
},
"user": "alice",
"group": ["user"],
},
}
}

總結

總之,與內置 RBAC 授權相比,OPA 允許更靈活的策略,尤其是在不使用其他 operator 的情況下。在我看來,將 OPA 直接集成為授權模塊和准入控制器會很好,但與此同時,Kubernetes Policy Controller 彌補了 Kubernetes 和 OPA 之間的差距。以下是我通過實踐得到的一些啟示:

  • 拒絕訪問特定的 CustomResourceDefinitions,如calico
  • 拒絕訪問特定的 ClusterRoles,如cluster-adminadmin
  • 只允許埠轉發到kube-system中的某些特定 Pod;
  • 創建一個映射,哪些 PodSecurityPolicies 可用於哪些 namespace ;
  • 除了一些預安裝的配置,允許用戶訪問 ValidatingWebhookConfigurations。

以上就是本文的全部內容,你是如何看待 OPA 作為 Kubernetes 的策略引擎?如果感興趣,不妨在讀完本文後,親自動手進行嘗試!

參考文獻

1.kubernetes.io/docs/refe

2.medium.com/capital-one-

3.itnext.io/kubernetes-co

4.github.com/open-policy-

5.openpolicyagent.org/doc


推薦閱讀:
相關文章