翻譯:小君君
技術校對:星空下的文仔、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”
:
“Your‘re 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-manager
和
system: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”
:
“Your’re not allowed to create/update/delete the StorageClass‘ceph’”
},
}]
{
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-admin
、
admin
;
只允許埠轉發到
kube-system
中的某些特定 Pod;
建立一個對映,哪些 PodSecurityPolicies 可用於哪些 namespace ;
除了一些預安裝的配置,允許使用者訪問 ValidatingWebhookConfigurations。
以上就是本文的全部內容,你是如何看待 OPA 作為 Kubernetes 的策略引擎?如果感興趣,不妨在讀完本文後,親自動手進行嘗試!
參考文獻
1。
https://
kubernetes。io/docs/refe
rence/access-authn-authz/rbac/
2。
https://
medium。com/capital-one-
tech/policy-enabled-kubernetes-with-open-policy-agent-3b612b3f0203
3。
https://
itnext。io/kubernetes-co
mpliance-with-open-policy-agent-3d282179b1e9
4。
https://
github。com/open-policy-
agent/gatekeeper
5。
https://www。
openpolicyagent。org/doc
s/how-do-i-test-policies。html