合作机构:阿里云 / 腾讯云 / 亚马逊云 / DreamHost / NameSilo / INWX / GODADDY / 百度统计
本文介绍K8s中的鉴权模块。对其4种鉴权模式都进行了概述讲解。结合例子着重对大家日常中使用最多的RBAC鉴权模式进行了说明。
《搞懂K8s认证》中,我们提到不论是通过kubectl客户端还是REST请求访问K8s集群,最终都需要经过API Server来进行资源的操作并通过Etcd。整个过程如下图1所示,可以分成4个阶段:
图1 K8s API请求访问过程
请求发起方进行K8s API请求,经过Authentication(认证)、Authorization(鉴权)、AdmissionControl(准入控制)三个阶段的校验,最后把请求转化为对K8s对象的变更操作持久化至etcd中。
其中认证主要解决的是请求来源能否访问的问题。即通过了认证,那么可以认为它是一个合法的请求对象。那么如何去决定请求对象能访问哪些资源以及对这些资源能进行哪些操作,便是鉴权所要完成的事情了。
鉴权的最终目的,是区分请求对象,限定操作的影响范围,让其使用最小的权限完成自己所要进行操作,从而进一步保证安全。权限控制的划分方式有许多种,K8s中提供了4种鉴权模式,分别为Node、ABAC、RBAC和Webhook。
默认情况下,我们可以从/etc/kubernates/manifests/kube-apiserver.yaml文件中查看apiserver启动时认证模式,片段如图2所示:
图2 kube-apiserver的认证参数
其中可以使用的参数如表1所示:
表1 鉴权模块参数标识表
参数配置 | 含义 | 一般的使用场景 |
--authorization-mode=ABAC | 使用基于属性的访问控制(ABAC) | 根据用户的用户名或者组名来控制其对集群资源的访问权限,适用于较小的组织或开发团队 |
--authorization-mode=RBAC | 使用基于角色的访问控制(RBAC) | 自定义ServiceAccount,绑定资源根据角色来控制资源的访问权限,适用于较大型的组织或者开发运维团队 |
--authorization-mode=Webhook | 使用HTTP回调模式,允许你使用远程REST端点管理鉴权 | 将鉴权角色交给外部服务进行处理,根据自身需求,定制和扩展鉴权策略,如自定义Webhook鉴权模块对跨云平台的应用进行集中的的访问控制 |
--authorization-mode=Node | 针对kubelet发出的API请求执行鉴权 | 验证节点身份,确保只有经过身份验证且具有所需权限的Node才能连接到K8s集群 |
--authorization-mode=AlwaysDeny | 阻止所有请求 | 一般仅用作测试 |
--authorization-mode=AlwaysAllow | 允许所有请求 | 不需要API请求进行鉴权的场景 |
如图2所示,可以同时配置多个鉴权模块(多个模块之间使用逗号分隔),排在靠前的模块优先执行,任何模式允许或拒接请求,则立即返回该决定,并不会与其他鉴权模块协商。
Node鉴权是一种特殊用途的鉴权模式,旨在对kubelet发出API请求进行授权。Node鉴权允许kubelet执行API的操作分成读和写两部分。读取操作控制范围为:services、endpoints、nodes、pods以及绑定到kubelet节点 Pod相关的secret、configmap、pvc和持久卷。写入操作的范围主要是节点和节点状态、Pod和Pod状态以及事件,若要限制kubelet只能修改自己的节点,则还需要在Apiserver启动时,开启NodeRestriction准入插件(见图2第二个红框)。
开启Node鉴权模块后,kubellet为了获取授权,必须使用一个特定规则的凭据,如图3所示:
图3 kubelet的证书凭据
从图中我们看到,kubelet使用了一个证书凭据,其中O=system:nodes表示其所在组,CN=system:node:paas-cnp-k8s-kce-01表示其用户名,满足了Node鉴权模块要求的组名必须为system:nodes,用户名必须为system:node:<nodeName>的要求。其中<nodeName>默认由hostname或kubelet --hostname-override选项提供指定,其必须与kubelet提供的主机名称精确匹配。
system:nodes是K8s的内置用户组,我们可以通过其默认的ClusterRoleBinding,如图4所示:
图4 system:nodes的ClusterRoleBinding内容
我们可以发现,它指示指向了system:node这个ClusterRole,并没有subjects的内容,即其没有绑定system:node:paas-cnp-k8s-kce-01用户也没有绑定system:nodes组。其正是因为K8s基于 Node鉴权模块来限制kubelet只能读取和修改本节点上的资源,并不是使用 RBAC来鉴权(涉及到部分RBAC的内容,下文会进行详解)。
基于属性的访问控制,K8s中可以表述将访问策略授予用户或者组。与RBAC不同的点在于,其策略是由任何类型的属性(用户属性、资源属性、对象、环境等)进行描述。
启用ABAC模式,类似于图2需要在apiserver启动时指定--authorization-mode=ABAC以及--authorization-policy-file=<策略文件路径> 。图5是K8s官网给出的一个策略样例文件:
图5 ABAC策略实例文件内容
文件中每行都是一个JSON对象,其中版本控制属性"apiVersion": "abac.authorization.kubernetes.io/v1beta1"和"kind": "Policy"可以理解成固定写法,是被K8s本身所使用,便于以后进行版本控制和转换。spec部分,其中user,来自于--token-auth-file的用户字符串,其指定的user名称必须与这个文件中的字符串相匹配;group,必须与经过身份验证的用户的一个组匹配, system:authenticated 匹配所有经过身份验证的请求。 system:unauthenticated 匹配所有未经过身份验证的请求。其他的匹配属性,主要描述被访问的访问,分为资源属性和非资源属性(其具体定义可参见官网)。readonly,主要限制是否只允许对资源进行 get、list 和 watch 操作,非资源属性只进行get操作。
例如:
{"apiVersion": "abac.authorization.kubernetes.io/v1beta1", "kind": "Policy", "spec": {"user": "alice", "namespace": "*", "resource": "*", "apiGroup": "*"}}
TOP