前言
在上一篇APIServer-P3-APIServer的认证机制中,讲述了请求进入后的认证过程,在通过认证之后,请求将进入鉴权环节,本篇就此展开。
审查请求属性
Kubernetes 仅审查以下 API 请求属性:
- 用户 - 身份验证期间提供的
user
字符串。 - 组 - 经过身份验证的用户所属的组名列表。
- 额外信息 - 由身份验证层提供的任意字符串键到字符串值的映射。
- API - 指示请求是否针对 API 资源。
- 请求路径 - 各种非资源端点的路径,如
/api
或/healthz
。 - API 请求动词 - API 动词
get
、list
、create
、update
、patch
、watch
、proxy
、redirect
、delete
和deletecollection
用于资源请求。 要确定资源 API 端点的请求动词,请参阅 确定请求动词。 - HTTP 请求动词 - HTTP 动词
get
、post
、put
和delete
用于非资源请求。 - Resource - 正在访问的资源的 ID 或名称(仅限资源请求)- 对于使用
get
、update
、patch
和delete
动词的资源请求,你必须提供资源名称。 - 子资源 - 正在访问的子资源(仅限资源请求)。
- 名字空间 - 正在访问的对象的名称空间(仅适用于名字空间资源请求)。
- API 组 - 正在访问的 API 组 (仅限资源请求)。空字符串表示核心 API 组
鉴权的描述
鉴权策略分类
目前支持6种鉴权策略,每种鉴权策略对应一个鉴权器,使用的鉴权策略需要在APIServer启动时以参数--authorization-mode
的形式指定,多种策略同时指定时使用’,’号连接:
策略分类有:
--authorization-mode=ABAC
基于属性的访问控制(ABAC)模式允许你 使用本地文件配置策略。--authorization-mode=RBAC
基于角色的访问控制(RBAC)模式允许你使用 Kubernetes API 创建和存储策略。--authorization-mode=Webhook
WebHook 是一种 HTTP 回调模式,允许你使用远程 REST 端点管理鉴权。--authorization-mode=Node
节点鉴权是一种特殊用途的鉴权模式,专门对 kubelet 发出的 API 请求执行鉴权。--authorization-mode=AlwaysDeny
该标志阻止所有请求。仅将此标志用于测试。--authorization-mode=AlwaysAllow
此标志允许所有请求。仅在你不需要 API 请求 的鉴权时才使用此标志。
与上一篇的认证模块不同的是,当配置多个鉴权模块时,鉴权模块按顺序检查,靠前的模块具有更高的优先级来允许或拒绝请求。
来看看现有的kubeadm部署集群启用的鉴权策略:
可以看到,默认启用了Node授权和RBAC授权模块。
鉴权结果
对于每一个请求的鉴权结果,有专门为其设计的健全结果描述结构体,如下:
vendor/k8s.io/apiserver/pkg/authorization/authorizer/interfaces.go:148
1 | type Decision int |
鉴权接口方法
vendor/k8s.io/apiserver/pkg/authorization/authorizer/interfaces.go:69
1 | // Authorizer makes an authorization decision based on information gained by making |
所有的鉴权模块(鉴权器)都要实现这个Authorize
方法,返回鉴权结果。
规则解析器
规则解析器可以根据认证之后所得到的用户信息,获取该用户对应的资源对象的操作权限。
1 | // RuleResolver provides a mechanism for resolving the list of rules that apply to a given user within a namespace. |
以这里的返回值类型ResourceRuleInfo
为例,默认的DefaultResourceRuleInfo
结构体是这样的:
vendor/k8s.io/apiserver/pkg/authorization/authorizer/rule.go:31
1 | // DefaultResourceRuleInfo holds information that describes a rule for the resource |
例如对pod资源的任意操作权限的描述可以描述为:
1 | DefaultResourceRuleInfo{ |
这个DefaultResourceRuleInfo对象描述的规则是,允许对所有api group 的pod资源进行的所有类型的操作,包括{“get”, “list”, “update”, “patch”,”create”, “delete”, “watch”, “deletecollection”}操作。
鉴权流程图
鉴权器
AlwaysAllow
和AlwaysDeny
这两种鉴权器很少使用,就不看了,直接略过.
ABAC鉴权器
简介
基于属性的访问控制(Attribute-based access control - ABAC)定义了访问控制范例,其中通过使用将属性组合在一起的策略来向用户授予访问权限。
启用ABAC鉴权器需要额外增加一个--authorization-policy-file=SOME_FILENAME
参数,指定一个json格式的文件预设鉴权策略,是一种静态的权限配置方式。json格式样例如下:
1 | // 授予pod资源的任意操作权限给用户podManager |
代码实现
pkg/auth/authorizer/abac/abac.go:224
1 | // Authorizer implements authorizer.Authorize |
–> pkg/auth/authorizer/abac/abac.go:117
1 | func matches(p abac.Policy, a authorizer.Attributes) bool { |
RBAC鉴权器
简介
基于角色(Role)的访问控制(RBAC)是一种基于组织中用户的角色来调节控制对 计算机或网络资源的访问的方法。
RBAC 鉴权机制使用 rbac.authorization.k8s.io
API 组 来驱动鉴权决定,允许你通过 Kubernetes API 动态配置策略。
通过创建Role
或ClusterRole
来描述具体的资源授权策略,再通过创建RoleBinding/ClusterRoleBinding将策略绑定到用户/群组/服务上。
RBAC模式的详细描述和使用样例请参考我之前的文章:
k8s(十四)、RBAC权限控制%E3%80%81RBAC%E6%9D%83%E9%99%90%E6%8E%A7%E5%88%B6.html)
代码实现
plugin/pkg/auth/authorizer/rbac/rbac.go:74
1 | func (r *RBACAuthorizer) Authorize(requestAttributes authorizer.Attributes) (authorizer.Decision, string, error) { |
对比规则和请求属性,返回true or false的visit方法:
plugin/pkg/auth/authorizer/rbac/rbac.go:62
1 | func (v *authorizingVisitor) visit(source fmt.Stringer, rule *rbacv1.PolicyRule, err error) bool { |
获取规则并调用visit方法的是VisitRulesFor
接口方法,找一下VisitRulesFor
方法:
pkg/registry/rbac/validation/rule.go:178
1 |
|
过程总结
参考代码片中的注释,rbac鉴权过程如下:
- 1.取到所有的clusterRoleBinding/roleBindings资源对象,遍历它们对比请求用户
- 2.对比roleBindings/clusterRoleBinding指向的用户(主体)与请求用户,相同则选中,不相同continue
- 3.对比规则与请求属性,符合则提前结束鉴权
Node鉴权器
上面有提过,node鉴权器是专为kubelet组件设计的,按照kubeadm集群的默认配置,它是排序在第一位的鉴权器,为什么把它放在后面再讲呢,因为node鉴权器本质上也是利用了rbac鉴权器,是通过为system:node
这个内置用户授权来实现的,来看一下。
默认Node规则生成
plugin/pkg/auth/authorizer/rbac/bootstrappolicy/policy.go:97
1 | func NodeRules() []rbacv1.PolicyRule { |
这里初始化了kubelet工作所需要的资源的权限,如(node/pod/cm/secret/pvc等)
Authorize代码实现
plugin/pkg/auth/authorizer/node/node_authorizer.go:80
1 | func (r *NodeAuthorizer) Authorize(attrs authorizer.Attributes) (authorizer.Decision, string, error) { |
WebHook鉴权器
简介
与上一篇中的WebHook认证器类似,WebHook鉴权器也是依赖于集群外部的鉴权服务器,将鉴权请求POST发送给外部的鉴权服务器。
Webhook
模式需要一个 HTTP 配置文件,通过 --authorization-webhook-config-file=SOME_FILENAME
的参数声明。
配置文件的格式使用 kubeconfig。在文件中,”users” 代表着 API 服务器的 webhook,而 “cluster” 代表着远程服务。
使用 HTTPS 客户端认证的配置例子:
1 | # Kubernetes API 版本 |
摘自官方文档Webhook 模式
代码实现
vendor/k8s.io/apiserver/plugin/pkg/authorizer/webhook/webhook.go:152
1 | func (w *WebhookAuthorizer) Authorize(attr authorizer.Attributes) (decision authorizer.Decision, reason string, err error) { |
总结
鉴权的流程与认证的流程大体类似,但也有所不同,例如认证器链的执行顺序是无序的,而鉴权器链的执行顺序是有序的(按参数指定的顺序)。另外鉴权器的数量没有认证器那么多,因此相对容易理解一些。