使用 OPA Gatekeeper 執(zhí)行 Kubernetes 策略
如果您所在的組織一直在使用 Kubernetes,您可能一直在尋找如何控制終端用戶在集群上的行為,以及如何確保集群符合公司政策。這些策略可能需要滿足管理和法律要求,或者符合最佳執(zhí)行方法和組織慣例。使用 Kubernetes,如何在不犧牲開發(fā)敏捷性和運(yùn)營(yíng)獨(dú)立性的前提下確保合規(guī)性?
例如,您可以執(zhí)行以下策略:
所有鏡像必須來(lái)自獲得批準(zhǔn)的存儲(chǔ)庫(kù) 所有入口主機(jī)名必須是全局唯一的 所有 Pod 必須有資源限制 所有命名空間都必須具有列出聯(lián)系的標(biāo)簽
在接收請(qǐng)求被持久化為 Kubernetes 中的對(duì)象之前,Kubernetes 允許通過(guò) admission controller webhooks 將策略決策與 API 服務(wù)器分離,從而攔截這些請(qǐng)求。Gatekeeper 創(chuàng)建的目的是使用戶能夠通過(guò)配置(而不是代碼)自定義控制許可,并使用戶了解群集的狀態(tài),而不僅僅是針對(duì)評(píng)估狀態(tài)的單個(gè)對(duì)象,在這些對(duì)象準(zhǔn)許加入的時(shí)候。Gatekeeper 是 Kubernetes 的一個(gè)可定制的許可 webhook ,它由 Open Policy Agent (OPA) 強(qiáng)制執(zhí)行, OPA 是 Cloud Native 環(huán)境下的策略引擎,由 CNCF 主辦。
Kubernetes 提供通過(guò)準(zhǔn)入控制器(Admission Controller)Webhooks 擴(kuò)展 API Server 功能的能力。在創(chuàng)建,更新或刪除資源時(shí),Kubernetes 就會(huì)調(diào)用這些 Webhooks。Gatekeeper 被作為驗(yàn)證 Webhook,并執(zhí)行 Kubernetes CRD 中定義的策略。除了使用準(zhǔn)入控制外,Gatekeeper 還提供了審核 Kubernetes 集群中現(xiàn)有資源并標(biāo)記當(dāng)前違反策略的功能。
安裝
賦予集群管理員權(quán)限:
??kubectl?create?clusterrolebinding?cluster-admin-binding?\
????--clusterrole?cluster-admin?\
????--user?admin
然后安裝 opa-gatekeeper,版本需要與k8s版本匹配,目前測(cè)試1.15版本使用3.4,1.19版本使用3.5,1.21使用3.6沒(méi)有問(wèn)題
kubectl?apply?-f?https://raw.githubusercontent.com/open-policy-agent/gatekeeper/release-3.5/deploy/gatekeeper.yaml
注意: 默認(rèn)gatekeeper不約束對(duì)資源的刪除,例如:opa中定義了某個(gè)用戶無(wú)法創(chuàng)建和更新的資源,但是這個(gè)用戶卻能刪除該資源,為了讓其沒(méi)有刪除權(quán)限,需要修改gatekeeper.yaml文件:
operations:
????-?CREATE
????-?UPDATE
????-?DELETE????//添加該行
示例
創(chuàng)建ConstraintTemplate模板:
kubectl?apply?-f?https://raw.githubusercontent.com/open-policy-agent/gatekeeper/master/demo/basic/templates/k8srequiredlabels_template.yaml
查看模板列表:
kubectl?get?ConstraintTemplate
查看模板是否有opa-rego語(yǔ)法錯(cuò)誤:
kubectl?describe?ConstraintTemplate?k8srequiredlabels???
k8srequiredlabels_template.yaml內(nèi)容如下:
apiVersion:?templates.gatekeeper.sh/v1beta1
kind:?ConstraintTemplate
metadata:
??name:?k8srequiredlabels???//?按需更改
spec:
??crd:
????spec:
??????names:
????????kind:?K8sRequiredLabels???//?按需更改
??????validation:
????????#?Schema?for?the?`parameters`?field
????????openAPIV3Schema:
??????????properties:????//?需要滿足的條件的參數(shù)
????????????labels:
??????????????type:?array
??????????????items:?string
??targets:
????-?target:?admission.k8s.gatekeeper.sh
??????rego:?|
????????package?k8srequiredlabels
?
????????violation[{"msg":?msg,?"details":?{"missing_labels":?missing}}]?{
??????????provided?:=?{label?|?input.review.object.metadata.labels[label]}??//?獲取到創(chuàng)建的對(duì)象的所有l(wèi)abel
??????????required?:=?{label?|?label?:=?input.parameters.labels[_]}??//?獲取到需要提供的label
??????????missing?:=?required?-?provided?//?rego語(yǔ)言支持集合相減,得到未滿足的label
??????????//?斷言未滿足的label數(shù)量>0,如果大于0,說(shuō)明條件滿足,
??????????//?violation為true,說(shuō)明違反了約束,返回錯(cuò)誤
??????????count(missing)?>?0?
??????????msg?:=?sprintf("you?must?provide?labels:?%v",?[missing])
????????}
創(chuàng)建約束 Constraints:
kubectl?apply?-f?https://raw.githubusercontent.com/open-policy-agent/gatekeeper/master/demo/basic/constraints/all_ns_must_have_gatekeeper.yaml
all_ns_must_have_gatekeeper.yaml 內(nèi)容如下:
apiVersion:?constraints.gatekeeper.sh/v1beta1
kind:?K8sRequiredLabels
metadata:
??name:?ns-must-have-gk
spec:
??match:
????kinds:
??????-?apiGroups:?[""]???
????????kinds:?["Namespace"]??//?表示這個(gè)約束會(huì)在創(chuàng)建命名空間的時(shí)候被應(yīng)用
??parameters:
????labels:?["gatekeeper"]??//傳遞給opa的參數(shù),此處表示一個(gè)key為labels,value為一個(gè)列表的字典,與ConstraintTemplate里的properties要匹配上,此處表示要?jiǎng)?chuàng)建的對(duì)象需要含有g(shù)atekeeper的label
注意 match 字段,它定義了將應(yīng)用給定約束的對(duì)象的范圍。它支持以下匹配器:
kind接受帶有 apiGroups 和 kind 字段的對(duì)象列表,這些字段列出了約束將應(yīng)用到的對(duì)象的組/種類。如果指定了多個(gè)組/種類對(duì)象,則資源在范圍內(nèi)只需要一個(gè)匹配項(xiàng)。scope接受 *、Cluster 或 Namespaced 決定是否選擇集群范圍和/或命名空間范圍的資源。(默認(rèn)為 *)namespaces是命名空間名稱的列表。如果已定義,則約束僅適用于列出的命名空間中的資源。命名空間還支持基于前綴的 glob。例如,namespaces: [kube-*] 匹配 kube-system 和 kube-public。excludeNamespaces是命名空間名稱的列表。如果已定義,則約束僅適用于不在列出的命名空間中的資源。ExcludedNamespaces 還支持基于前綴的 glob。例如,excludedNamespaces: [kube-*] 匹配 kube-system 和 kube-public。labelSelector是標(biāo)準(zhǔn)的 Kubernetes 標(biāo)簽選擇器。namespaceSelector是針對(duì)對(duì)象的包含名稱空間或?qū)ο蟊旧淼臉?biāo)簽選擇器,如果對(duì)象是名稱空間。name 是對(duì)象的名稱。如果已定義,則匹配具有指定名稱的對(duì)象。Name 還支持基于前綴的 glob。例如,名稱:pod-* 匹配 pod-a 和 pod-b。
請(qǐng)注意,如果指定了多個(gè)匹配器,則資源必須滿足每個(gè)頂級(jí)匹配器(種類、名稱空間等)才能在范圍內(nèi)。每個(gè)頂級(jí)匹配器都有自己的語(yǔ)義來(lái)確定什么是匹配。空匹配器被認(rèn)為是包含的(匹配所有內(nèi)容)。還要了解命名空間、excludedNamespaces 和 namespaceSelector 將匹配未命名空間的集群范圍資源。為避免這種情況,請(qǐng)將范圍調(diào)整為 Namespaced。
示例
apiVersion:?constraints.gatekeeper.sh/v1beta1
kind:?K8sPodLabels
metadata:
??name:?pod-must-have-gk
spec:
??match:
????kinds:
??????-?apiGroups:?[""]
????????kinds:?["Pod"]
????labelSelector:
??????matchExpressions:
????????-?key:?app
??????????operator:?In
??????????values:?[nginx1]
????namespaces:?["ns-test"]
??parameters:
????labels:?["gatekeeper"]
查看Constraints:
kubectl?get?constraints
測(cè)試
創(chuàng)建如下的命名空間:
apiVersion:?v1
kind:?Namespace
metadata:
??name:?ns-test
??labels:
????a:?b
????#gatekeeper:?"abc"
此時(shí)不給命名空間添加key為gatekeeper的label,會(huì)報(bào)錯(cuò):
Error?from?server?([ns-must-have-gk]?you?must?provide?labels:?{"gatekeeper"}):?error?when?creating?"ns-test.yaml":?admission?webhook?"validation.gatekeeper.sh"?denied?the?request:?[ns-must-have-gk]?you?must?provide?labels:?{"gatekeeper"}
#gatekeeper: "abc" 這行的注釋打開,則能成功創(chuàng)建。
獲取input
如果需要?jiǎng)?chuàng)建自己的約束,但是不知道傳入的參數(shù)即input是什么,可以在創(chuàng)建模板時(shí)violation只保留下面幾行,此時(shí)創(chuàng)建對(duì)象時(shí)必定會(huì)失敗,然后獲取到輸出的錯(cuò)誤信息,里面即包含所有input信息,之后再通過(guò)rego語(yǔ)法去獲取需要的數(shù)據(jù)即可
violation[{"msg":?msg}]?{
????msg?:=?sprintf("input:??%v",?[input])
}
案例1
要求:只能允許"user1", "user2", "kubernetes-admin"這三個(gè)用戶擁有創(chuàng)建、更新、刪除default命名空間中l(wèi)abel為 app: nginx1 的pod。
創(chuàng)建約束模板:
[root@master1?opa]#?cat?k8srequiredusers_template.yaml?
apiVersion:?templates.gatekeeper.sh/v1beta1
kind:?ConstraintTemplate
metadata:
??name:?k8srequiredusers
spec:
??crd:
????spec:
??????names:
????????kind:?K8sRequiredusers
??????validation:
????????#?Schema?for?the?`parameters`?field
????????openAPIV3Schema:
??????????properties:
????????????users:
??????????????type:?array
??????????????items:?string
??targets:
????-?target:?admission.k8s.gatekeeper.sh
??????rego:?|
????????package?k8srequiredusers
?
????????violation[{"msg":?msg}]?{
??????????//?把創(chuàng)建時(shí)的用戶名放在一個(gè)集合里
??????????user?:=?{?input.review.userInfo.username?}???
??????????//?獲取允許創(chuàng)建該pod的用戶集合
??????????permitUser?:=?{user?|?user?:=?input.parameters.users[_]}
??????????//?集合-集合
??????????allow?:=?permitUser?-?user
??????????//?如果減完之后集合還相等,說(shuō)明這個(gè)用戶沒(méi)有在允許的集合中,不滿足約束條件
??????????allow?==?permitUser
??????????msg?:=?sprintf("user?%v?not?allowd",?[user])
????????}
創(chuàng)建約束:
[root@master1?opa]#?cat?requiredusers_constraind.yaml?
apiVersion:?constraints.gatekeeper.sh/v1beta1
kind:?K8sRequiredusers
metadata:
??name:?required-users
spec:
??match:
????kinds:
??????-?apiGroups:?[""]
????????kinds:?["Pod"]
????labelSelector:
??????matchExpressions:
????????-?key:?app
??????????operator:?In
??????????values:?[nginx1]
????namespace:?["default"]
??parameters:
????users:?["user1",?"user2",?"kubernetes-admin"]
創(chuàng)建pod,用kubernetes-admin用戶創(chuàng)建這個(gè)pod,能正常創(chuàng)建,同時(shí)更新、刪除也能成功:
[root@master1?opa]#?cat?pod.yaml?
apiVersion:?v1
kind:?Pod
metadata:
??name:?pod2
??labels:
????app:?nginx1
spec:
??containers:
??-?name:?nginx-pod
????image:?nginx:1.12
????imagePullPolicy:?Never
使用myuser用戶創(chuàng)建、刪除、更新均不成功,會(huì)提示約束報(bào)錯(cuò)信息。
案例2
ConfigMap、Secret、PersistentVolumeClaim必須包含security標(biāo)簽,并且標(biāo)簽必須為s1,s2,s3,s4中之一
apiVersion:?templates.gatekeeper.sh/v1beta1
kind:?ConstraintTemplate
metadata:
??name:?resourcesecurityclassification
spec:
??crd:
????spec:
??????names:
????????kind:?ResourceSecurityClassification?
??????validation:
????????#?Schema?for?the?`parameters`?field
????????openAPIV3Schema:
??????????properties:
????????????labelkey:
??????????????type:?string
????????????labelvalues:
??????????????type:?array
??????????????items:?string
??targets:
????-?target:?admission.k8s.gatekeeper.sh
??????rego:?|
????????package?resourcesecurityclassification?
?
????????violation_label_and_value(provided,?required)?=?allow?{
????????????rlt?:=?provided?-?required
????????????allow?:=?(rlt?!=?provided)
????????}
?
????????violation[{"msg":?msg}]?{
????????????providedlabels?:=?{label?|?label?:=?input.review.object.metadata.labels[_]}
????????????providedkey?:=?{key?|?input.review.object.metadata.labels[key]}
????????????requiredkey?:=?input.parameters.labelkey
????????????requiredlabels?:=?{label?|?label?:=?input.parameters.labelvalues[_]}
????????????kind?:=?input.review.object.kind
????????
????????????k?:=?violation_label_and_value(providedkey,?{?requiredkey?})
????????????v?:=?violation_label_and_value(requiredlabels,?providedlabels)
????????????{?k?}?&?{?v?}?!=?{?true?}
????????????msg?:=?sprintf("[%v]?must?have?label:?[%v]?and?must?have?one?of?the?following?values:?%v",?[kind,?requiredkey,?requiredlabels])
????????}
?
---
apiVersion:?constraints.gatekeeper.sh/v1beta1
kind:?ResourceSecurityClassification
metadata:
??name:?resources-must-have-security-classification
spec:
??match:
????kinds:
??????-?apiGroups:?[""]
????????kinds:?["ConfigMap","Secret","PersistentVolumeClaim"]
??parameters:
????labelkey:?"security"?
????labelvalues:?["s1",?"s2",?"s3",?"s4"]
官方地址:https://open-policy-agent.github.io/gatekeeper/website/docs/install
原文鏈接:https://blog.csdn.net/weixin_42758299/article/details/120978564
