在项目中, Kubernetes 集群会对 Kubernetes APIServer 的每个请求都进行身份验证和授权管理。在此过程中,授权管理通常由 RBAC 授权模块来实现,但开发者也可以选择其他组件,如 Open Policy Agent(OPA)。
关于授权,绝大多数要求可以通过 Roles 和 RoleBindings 简单地使用 RBAC 授权模块来实现 [1]。但 RBAC 在设计上仅限于白名单。即对于每个请求,它会选择检查其中的一个 Roles 和 RoleBindings 是否适用,然后批准请求。
如果你有很多这样的用例,你就要通过运营商来实现很多自定义的逻辑,但是你需要知道这些用例可能不会被扩展。因为这样做就会有很多的运营商和随附的 RBAC 角色,我们将很难控制用户实际拥有的权利。下面,我们将展示如何通过 OPA 轻松实现上述两种情况。
除了本文探讨的情况,一些高级用例也可以通过 Dynamic Admission Control 实现,如 ValidatingWebhook 或 MutatingWebhook。这里为大家推荐两篇关于如何使用 OPA 的博客:Policy Enabled Kubernetes with Open Policy Agent [2]以及 Kubernetes Compliance with Open Policy Agent [3]。
作为参考,Webhook 授权模块由 SubjectAccessReviews 决定,而 ValidatingWebhook 和 MutatingWebhook 则由 AdmissionReviews 决定。在实践中,我们通过授权模块和 MutatingWebhook 来集成 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-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" : "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-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
推荐阅读: