玩转 Kubernetes 权限控制 AuthN/Z
刘搏
才云科技平台软件工程师
毕业于浙江大学
加入才云后先后从事 Kubernetes 监控和权限相关的工作。
摘要
AuthN/Z 是系统设计中相当重要的一环,它在很大程度上决定了 Kubernetes 能否成为一个企业级的解决方案。然而,严格的权限管理也给 Kubernetes 的使用带来了一定的麻烦,大大提高了 Kubernetes 的入门门槛。
本文旨在帮助大家系统地认识 Kubernetes 的 AuthN/Z 的功能和实现。希望大家在部署和使用 Kubernetes 的过程中不会掉入权限的泥沼。
首先简单介绍一下 AuthN/Z 的异同及在 Kubernetes 内的实现。AuthN 系统主要用于认证 (Authentication),决定谁访问了系统。AuthZ 系统主要用于授权 (Authorization),决定访问者具有什么样的权限。
在 Kubernetes 系统中,AuthN 完成了用户的认证并且获取了用户的相关信息(如 Username,Groups 等)。而 AuthZ 则根据这些信息匹配预定义的权限规则,然后决定某个 API 请求是否被允许。
AuthN 系统
Kubernetes 的 AuthN 系统主要完成了以下工作:
根据配置验证用户凭证,通常是 Bearer Token 或者 Basic Auth Password。
解析用户信息,包括 Username,Groups,Uid 等。这些信息将用于之后的 Authz 系统授权。
通过传入 --client-ca-file 到 Apiserver 开启。其中证书的 /CN (common name)表示用户名,/O (organization)表示 Groups。
Client Cert 模式通常用于某些受信任的组件访问 Apiserver,如 Kubernetes 各个组件访问 Apiserver。
通过传入 --token-auth-file 到 Apiserver 开启。以下是其中一条记录的模版。HTTP 请求在 Header 中传入 Authorization: Bearer Token 来认证。
通过传入 --basic-auth-file 到 Apiserver 开启。以下是其中一条记录的模版。HTTP 请求在 Header 中传入 Authorization:Basicbase64(user:password)来认证。
Service Account Token 主要是用来给 Pod 提供访问 Apiserver 的权限。当 Pod 通过 Service Account 访问 Apiserver 时,用户名为 system:serviceaccount: (NAMESPACE):(SERVICEACCOUNT),并且属于system: serviceaccounts和system: serviceaccounts:(NAMESPACE) 这两个 Group。当一个 Pod 使用 InClusterConfig 创建 Client 访问 Apiserver 时,Client 会自动载入 Service Account 的 Token。
OIDC 是除了 WebHook 外 Kubernetes 提供的唯一一个动态的 AuthN 方案。相比较于上面几种方案的小打小闹,OIDC 提供了标准的 AuthN 流程,真正能够作为 Kubernetes 系统用户认证的企业级解决方案。
OpenID Connect 协议是基于 Oauth2.0 协议之上的一个认证协议。OIDC 的认证流程跟 Oauth2.0 类似,不过除了返回 access_token 以外还返回了 id_token。Kubernetes 使用id_token 来认证用户。OIDC 协议中的 id_token 根据 JWT (Json Web Token) 协议标准实现。Kubernetes 通过 id_token 的 Claim 获取用户信息。比如 Groups, Username 等。
以下是 OIDC 认证的流程:
Apiserver 需要配置以下参数:
参数名 | 说明 |
–oidc-issuer-url | OIDC 服务访问地址,如 https://accounts.google.com |
–oidc-client-id | OIDC 协议的 Client ID,和 Oauth2.0 的 Client_id 一样 |
–oidc-username-claim | 用户名从哪个 Claim 获取,可以取 Sub, Email, Name 等值 |
–oidc-groups-claim | 用户所在的 Groups , 从 Groups 这个 Claim 里获取 |
–oidc-ca-file | 用于信任 OIDC 服务的 https |
为了防止不同的 Issuer 导致的用户名冲突,当 --oidc-username-claim 取值不是 Email 时,AuthZ 所使用的真正的用户名会加上 Issuer 前缀,如下所示:
不过 1.8 后添加了 Claim Prefix 的参数 --oidc-username-prefix 和 --oidc-groups-prefix,显然上面这种丑陋的格式总是会让人很不高兴。
当你需要外接一个用户系统的时候,你总是需要一个 Webhook。
通过传入 --authentication-token-webhook-config-file 开启,另外还要添加
--runtime-config=authentication.k8s.io/v1beta1=true。
Webhook 的配置文件如下:
Webhook Service 需要实现 TokenReview 的接口:
Kubernetes 的 AuthZ 系统主要完成了以下几件事情:
解析 HTTP 请求,获取请求的各种属性
根据属性和 AuthN 获取的用户信息,依次匹配 AuthZ 规则,如果成功则通过,如果全部失败则返回禁止访问。
不同于 AuthN 方案,AuthZ 方案在 Kubernetes 中和其 API 风格有相当大的关联。由于严格遵循 RESTful 标准定义 API,Kubernetes 在提取 HTTP 请求属性和定义 AuthZ 规则等方面有了极大的便利。
AuthZ 系统的核心接口如下:
(/apiserver/pkg/authorization/authorizer/interfaces.go
)
每一个 http 请求都会创建一个 Attributes,从该接口的定义可以发现,Kubernetes 将 http 请求的 Path 参数解析并分解成 APIGroup, APIVersion 等属性。然后 Authorizer 根据这些属性匹配对应的规则完成 Authz。
下面是 Kubernetes 提供的两种 AuthZ 方案 —— ABAC 和 RBAC。
ABAC
ABAC
ABAC 全称 Attribute Based Access Control(基于属性的访问控制)。通过 --authorization-mode=ABAC 开启,并且通过 --authorization-policy-file 指定策略文件。
以下是 ABAC 的一条记录的例子:
可以发现 ABAC 定义的字段基本上就是来自于上述的 Attributes 接口能够获取的信息。另外值得一提的是 Kubernetes 中的 ABAC 没有动态方案,修改策略文件后必须重启 Apiserver。
RBAC
RBAC 全称 Role Based Access Control(基于角色的访问控制), 通过 --authorization-mode=RBAC 开启。
目前和 RBAC 相关的 Resource 有以下 4 种:
Role
RoleBinding
ClusterRole
ClusterRoleBinding
Role 和 RoleBinding 是 NameSpace 下的资源,而 ClusterRole 和 ClusterRoleBinding 是系统级的资源。1.8 后 RBAC 所属的资源已经从 v1beta1 升级到 v1。
Role
Role 的例子如下:
ClusterRole
ClusterRole 的例子如下:
ClusterRole 可以用来定义全局的 Resource。当使用 ClusterRoleBinding 绑定时,表示能访问所有 NameSpace 下的资源(如上述的 secrets),当使用 RoleBinding 绑定时,表示只能访问 RoleBinding 所属的 NameSpace 下的资源。
RoleBinding
RoleBinding 的例子如下:
RoleBinding 负责绑定 Subjects 和某一个 Role 或者 ClusterRole。
ClusterRoleBinding
ClusterRoleBinding 的例子如下:
ClusterRoleBinding 能够绑定 Subjects 和 ClusterRole。
Subjects
Subjects 分为以下 3 种类型,Subjects 来自于 AuthN 的结果。
User
Group
ServiceAccount
Webhook
AuthZ 系统也可以通过 Webhook 实现。不过比起 AuthN,AuthZ 系统通常没有必要使用 Webhook。
通过传入 --authorization-webhook-config-file 开启,另外还要添加
--runtime-config=authorization.k8s.io/v1beta1=true。
Webhook 的配置文件如下:
Webhook Service 需要实现 SubjectAccessReview 的接口
Kubernetes 的 AuthN 系统主要是认证用户并获取用户对应的 Subject。比如 User,Group,ServiceAccount。而 AuthZ 系统主要是根据用户的 Subject 和 http 请求获取的属性依次匹配定义的规则(ABAC 或 RBAC)。
目前而言 Kubernetes 的 RBAC 系统能够较好的处理大部分的授权问题,不过也有一定的缺点,比如只能定义用户是否有 LIST 资源的权限,而无法定义用户 LIST 一部分资源的权限。在真正使用 Kubernetes 的 AuthZ 系统的时候建议以 NameSpace 为粒度做权限控制。