互联网技术 / 互联网资讯 · 2023年12月14日

Kubernetes中基于标签的权限控制实现与Webhook的应用

Kubernetes提供了基于名称空间的权限控制。在AkRAIno ICN项目中,我们面临一些复杂的权限需求:多个用户能够在同一名称空间内创建、更新或删除某种资源,但却无法更新或删除他人创建的对象。

为了解决这一问题,我们设计并实现了一种基于标签的权限控制机制,该机制利用Webhook在Kubernetes中进行权限管理。Webhook通常用于验证资源或设置资源的默认值,而在本文中,我们将其应用于权限控制。

权限系统设计

在Kubernetes中,用户或服务账户可以与一个或多个角色进行绑定。每个角色都定义了特定的权限规则。例如,sdewan-test角色可以在默认名称空间中创建或更新类型为Mwan3Rule的自定义资源实例(CR),并且能够获取Mwan3Policy CR。

我们通过JSON格式的注释sdewan-bucket-type-permission来扩展角色的权限。

在这些注释中,我们可以定义基于标签的权限。例如,以下角色扩展了sdewan-test角色的权限:sdewan-test仅能创建或更新带有标签sdewan-bucket-type=app-intent或sdewan-bucket-type=k8s-service的Mwan3Rule(JSON键指定了自定义资源类型)CR。同时,它只能获取带有标签sdewan-bucket-type=app-intent的Mwan3Policy CR。

实际上,我们还支持通配符匹配。例如,可以使用Mwan3*同时匹配Mwan3Policies和Mwan3Rules。

Kubernetes Webhook负责解析角色注释。简单来说,准入Webhook可以被视为在Kubernetes集群中作为pod运行的Web服务。

当Kubernetes API接收到请求时,kube-API会在将对象保存至etcd之前调用Webhook API。如果Webhook返回allowed=True,kube-API将继续将对象持久化存储在etcd中;否则,kube-API将拒绝该请求。

Webhook请求主体中包含一个名为UserInfo的字段,该字段指示发出Kubernetes API请求的用户。Webhook可以从用户信息中获取角色信息,并进一步获取角色的注释。通过将注释中描述的标签级别权限与CR标签进行比较,Webhook能够决定是否允许该请求。

实施权限控制系统

我们通过AkRAIno ICN项目中的kubebuilder框架实现了基于标签的权限控制系统。假设已经实现了一些自定义资源定义(CRD),例如Mwan3Policy和Mwan3Rule,以及相应的控制器。

Kubebuilder可以生成基本的CRD、控制器代码和Webhook代码。为了创建新的Webhook,我们可以运行以下kubebuilder命令:

该命令利用controller-runtime构建器来创建验证Webhook,并会创建一个Webhook服务器,该服务器接受来自kube-API服务器的HTTPS请求。同时,它还会生成解析HTTP请求主体并将其转换为CRD结构实例的代码。

开发人员只需编写代码以验证CRD实例的内容。这对于大多数Webhook场景而言是有效的,但由于我们需要处理位于HTTPS请求正文中的UserInfo,而不是CRD实例,因此这一方法无法满足我们的需求。

使用Webhook为Kubernetes实现基于标签的权限控制

我们重用了kubebuilder生成的Webhook服务器,并实现了自己的处理程序。该处理程序接受“admission.request”作为输入,其中包含UserInfo。在处理程序中,我们获取用户的角色信息和CR标签。

获取用户角色信息

UserInfo位于请求正文中。为了从UserInfo中提取角色信息,处理程序必须向kube-API请求用户的角色信息。处理程序使用serviceaccount令牌进行身份验证,并将请求发送至kube-API。处理程序首先请求用户的角色绑定信息,然后再从角色绑定信息中提取角色信息。默认情况下,角色绑定资源在“.subjects”字段上没有索引器,这意味着我们无法在kube-API请求中过滤角色绑定,除非为角色绑定添加以下索引器:

获取CR信息

用户的请求可能包括创建、更新或删除资源。对于创建或更新请求,处理程序从请求正文中提取CR信息。而对于删除请求,处理程序只能获取CR名称,而无法获取完整实例,因此需要调用kube-API以获取CR信息。

考虑角色和ClusterRole

除了角色,还可以在ClusterRole中定义用户的权限。两者的区别在于,角色的权限始终在单个名称空间中定义,而ClusterRole可以跨整个集群定义权限。因此,我们还需要检查ClusterRole中的注释。在解析角色信息时,我们仅关注与CR处于同一名称空间的角色。

测试与实验

接下来,我将说明如何测试和实验基于标签的权限。在ICN中,此功能是通过kubebuilder与某些CRD/控制器共同开发的。Webhook支持HTTPS,但不支持HTTP,因此我们需要为Webhook服务器提供认证。

我们使用cert-Manager插件来生成Webhook服务器的证书。同时,将证书注入Webhook配置中,以便kube-API在发送Webhook请求时能够使用该证书。对于开发或本地测试用例,若Webhook在本地而非Pod中运行,则需要手动配置证书。

一旦建立了网络连接,我们便可以为测试创建角色和角色绑定。让我们创建以下角色并将其绑定到用户。

允许用户创建标签为“sdewan-bucket-type:app-intent”的Mwan3Policies,但不能创建其他标签。具体而言,用户能够创建左侧的CR,而无法创建右侧的CR。

若尝试创建右侧的CR,将会收到错误消息:“ERROR FROM SERVER (Your Roles don’t have the permission): Error when creating “config/samples/BATch_v1alpha1_Mwan3policy.yaml”。

使用Webhook为Kubernetes实现基于标签的权限控制

结论

Webhook是Kubernetes的一个强大功能,为其提供了更大的灵活性。开发人员可以利用Webhook实现多种有用的功能。

Controller-Runtime项目提供了构建工具,使得我们可以轻松创建两种类型的Webhook:验证Webhook和Mutating Webhook。验证Webhook用于验证kube-API的资源,而Mutating Webhook则可以更新资源字段的值,例如设置默认值。

有时,这两种Webhook都无法满足我们的需求。在本文中,我们需要获取不在资源正文中的UserInfo,这使得我们必须自行开发大部分处理程序代码,而不是依赖于构建工具。