Kubernetes 安全权限管理深度剖析
目录
3. ServiceAccount Admission Controller
摘要
Kubernetes 作为当下应用最普遍的容器集群管理工具,详细了解它的认证鉴权机制是非常有必要的。本文的主要内容就是增进大家对 k8s 的认证和鉴权模块的了解,其中包括 kubernetes 准入控制及 RBAC 的集群认证与鉴权机制。
一、集群准入控制机制详解
Kubernetes 自身并没有用户管理能力,无法像操作 Pod 一样,通过 API 的方式创建/删除一个用户实例,也无法在 etcd 中找到用户对应的存储对象。在 Kubernetes 的访问控制流程中,用户模型是通过请求方的访问控制凭证产生的。

上图是 k8s 的安全全景图,安全控制机制包括两部分:部署态的安全控制和运行态的安全控制。其中,部署态的安全控制机制分为认证、鉴权、Admission(准入控制)、Pod SecurityContext。运行态的安全控制是 Network policy。接下来,本文的主要内容将围绕认证和鉴权模块展开。
1. Kubernetes API 访问控制
1) 认证
集群创建脚本或者集群管理员配置 API 服务器,使之运行一个或者多个身份认证组件。认证步骤是处理输入的整个 HTTP 请求,主要检查头部或者客户端证书。
认证模块包括客户端证书、密码、普通令牌、引导令牌和 JSON Web 令牌(JWT,用于服务账户),API Server 依次尝试每个验证模块,直到其中一个成功。如果请求认证不通过,服务器将以 HTTP 状态码 401 拒绝该请求。
2) 鉴权
认证通过后,才能进入后续的鉴权模块。鉴权主要是识别具体用户的信息,并根据用户和请求的信息进行鉴权。kubernetes 鉴权要求使用公共 REST 属性与现有的组织范围或云提供商范围的访问控制系统进行交互。
鉴权请求必须包含请求者的用户名、请求的行为以及受该操作影响的对象。如果现有策略声明用户有权完成请求的操作,那么该请求将会被鉴权通过。
关于认证和鉴权模块在服务器端的处理流程可以参考下图:

如上图所示,当 Token、X509、WebHook 等流程出现问题时,会直接返回客户端状态码 401。当认证模块没有问题,请求会进入鉴权模块,如果 ABAC、RBAC、WebHook 等流程出现异常,会直接返回客户端状态码 403。
Kubernetes 支持多种鉴权模块,例如 ABAC 模式、RBAC 模式和 Webhook 模式等,管理员创建集群时,他们应该在 API 服务器中配置需要使用的鉴权模块。举一个例子来加强一下理解,具体内容如下图所示:

如果 Bob 在 projectCaribou 名字空间中请求写(create 或者 update)对象,其鉴权请求将被拒绝。如果 Bob 在非 projectCaribou 名字空间中请求读取(get)对象,其鉴权也会被拒绝。
2. Admission controller
Admission Controller 实现了对于 Kubernetes 集群的准入控制,如下图所示,Admission Controller 以插件的形式内置于 Kubernetes APIServer,在 APIServer 对请求的处理链路中发挥作用。
一般 RESTful 请求进入 APIServer 之后,主要包含 Mutating 和 Validation 两类操作,具体的操作都由相应的插件完成。Mutating 可以对请求中的资源对象进行修改而 Validation 则仅进行校验。Mutating 和 Validation 之间还有一个名为 Object Schema Validation 的操作,用于进行一些对于资源对象通用的校验,例如 Pod 中所有容器的名字都要唯一等等。最后,完成与 etcd 之间的交互。

二、集群认证机制剖析
所有的 Kubernetes 集群都有两类用户:有 Kubernetes 管理的服务账号和普通用户。尽管无法通过 API 调用来添加普通用户,Kubernetes 仍然认为能够提供由集群的证书机构签名的合法证书的用户是通过身份认证的用户。基于这样的配置,Kubernetes 使用证书中的‘subject’的通用名称字段来确定用户名。接下来,基于角色访问控制(RBAC)子系统会确定用户是否有针对某资源执行特定的操作。
与此不同,Service Account 是 Kubernetes API 所管理的用户。它们被绑定到特定的名字空间,或者由 API 服务器自动创建,或者通过 API 调用创建。服务账号与一组以 Secret 保存的凭证相关,这些凭据会被挂载到 Pod 中,从而允许集群内的进程访问 Kubernetes API。
Kubernetes 使用身份认证插件利用客户端证书、持有者令牌(Bearer Token)、身份认证代理(Proxy)或者 HTTP 基本认证机制来认证 API 请求的身份。

如上图所示,Kubernetes 有非常多的认证方式,接下来,本文重点介绍 service account 认证方式。
1. service account 样例
持有者令牌会挂载到 Pod 中可预知的位置,允许集群内进程与 API 服务器通信,服务账号也可以使用 Pod 规约的 serviceAccountName 字段显式地关联到 Pod 上。
Service-account-token 的 secret 资源包的数据有三部分:
a. Ca.crt:这是 API Server 的 CA 公钥证书,用于 Pod 中的 Process 对 API Server 对服务端数字证书进行校验时使用的。
b. Namespace:这是 secret 所在的 namespace 的值的 base64 编码。
c. Token:该 token 就是由 service-account-key-file 的值签署生成。
已签名的 JWT 可以用于持有者令牌,并将被认证为所给的服务账号。服务账号认证被身份认证后,所确定的用户名为 system:serviceaccount:<名字空间>:<服务账号>,并被分配到用户组 system:serviceaccounts 和 system:serviceaccounts:<名字空间>。

2. Service Account
Service Account Token 是一种比较特殊的认证机制,适用于上文中提到的 pod 内部服务需要访问 apiserver 的认证情况,默认 enabled。
Service Account 为 k8s 默认开放认证方式。Kube-apiserver 的启动参数--service-account-key-file=key.pem 指定 pem 文件,用以生成 bearer token;--service-account-lookup=true/false 表示在删除 service account 后其 token 是否被吊销。具体流程如下图所示:

3. ServiceAccount Admission Controller
当 Pod 被创建或者更新时,它会同步修改 Pod。当 Pod 被创建或者更新时,它会进行以下操作:
1) 设置 ServiceAccount:如果该 Pod 没有指定,则设置 default ServiceAccount。
2) 校验指定的 ServiceAccount 是否存在:否则拒绝该 Pod。
3) 自动挂载选项。
4) 创建 volumeSource 挂载目录。
5) 设置 imagePullSecrets。
具体流程如下图所示:

4. TokenController
TokenController 作为 kube-controller-manager 的一部分运行,以异步的形式工作。其职责包括:
1) 检测 ServiceAccount 的创建并创建相应的 Secret 以允许访问 API。
2) 检测 ServiceAccount 的删除并删除所有的 Secret。
3) 检测 ServiceAccount 的 Secret 添加,保证相应的 ServiceAccount 存在,如有需要,向 Secret 中添加令牌。
4) 检测服务账号令牌 Secret 的删除,从相应的 ServiceAccount 中移除引用。
5) List,watch k8s apiserver 对于命名空间的创建、删除;在新创建的名称空间下创建一个名为“default”的 service account。
5. 认证流程源码分析
Kube-apiserver 在权限相关代码从 k8s.io/apiserver/pkg/server/config.go 中 defaultBuildHandlerChain 函数开始处理请求中的认证逻辑,源码如下图所示:

defaultBuildHandlerChain 中包含了多种 filter(如认证、链接数检验、RBAC 权限检验等),在 WithAuthentication 中完成认证流程,在 WithAuthorization 中完成鉴权流程。WithAuthentication 函数中通过 auth.AuthenticateRequest(req)处理请求。
三、集群鉴权机制 RBAC 剖析
1. 鉴权模块
1) Node,一个专用鉴权组件,根据调度到 kubelet 上运行的 Pod 为 kubelet 授予权限。
2) ABAC,基于属性的访问控制(ABAC)定义了一种访问控制范型,通过使用将属性组合在一起的策略,将访问权限授予用户。策略可以使用任何类型的属性(用户属性、资源属性、对象、环境属性等)。
3) RBAC,基于角色的访问控制(RBAC)是一种基于企业内个人用户的角色来管理对计算机网络资源的访问的方法。在此上下文中,权限是单个用户执行特定任务的能力,例如查看、创建或者修改文件。要启动 RBAC,需要使用--authorization-mode=RBAC 启动 API 服务器。
4) Webhook,一种 HTTP 回调,发生某些事情时会调用 HTTP POST,通过 HTTP POST 进行简单的事件通知。实现 Webhook 的 web 应用程序会在发生某些事情时将消息发布到指定的 URL。
2. RBAC 鉴权策略
RBAC 的鉴权策略可以利用 kubectl 或者 kubernetes API 直接进行配置。RBAC 可以授权给用户,让用户有权进行授权管理,这样就可以无需接触节点,直接进行授权管理。RBAC 在 kubernetes 中被映射为 API 资源和操作。RBAC API 声明了四种 kubernetes 对象:Role、ClusterRole、RoleBinding 和 ClusterRoleBinding,四者的关系如下图所示:

3. 命名空间及权限详解
1) Role 和 ClusterRole
a. Role 是只作用于命名空间级别的,用于定义命名空间内资源权限集合。
b. ClusterRole 则用于集群级别的资源权限集合,它们都是标准的 API 资源类型。
c. 一般来说,ClusterRole 的许可授权作用于整个集群,因此常用于控制 Role 无法生效的资源类型,包括集群级别的资源、非资源类型的端点和作用于所有命名空间的资源。
2) RoleBinding 和 ClusterRoleBinding
a. RoleBinding 用于将 Role 上的许可权限绑定到一个或一组用户之上,它隶属于且仅能作用于一个命令空间。绑定时,可以引用同一名称中的 Role,也可以引用集群级别的 ClusterRole。
b. ClusterRoleBinding 则把 ClusterRole 中定义的许可权限绑定在一个或者一组用户之上,它仅可以引用集群级别的 ClusterRole。
c. Role、RoleBinding、ClusterRole 和 ClusterRoleBinding 的关系如下图所示:

RBAC 是让用户能够访问 kubernetes API 资源的授权方式,其中,role 角色是一系列权限的集合。Role binding 把角色映射到用户,从而让用户继承角色在 namespaace 中的权限。ClusterRoleBinding 让用户继承 ClusterRole 在整个集群中的权限。另外,还要考虑 cluster roles 和 cluster role binding。RBAC 被 kubernetes 深度集成,并使用他给系统组件进行授权。System Roles 一般具有前缀 system:,很容易识别。
结尾
本文主要讲述了 kubernetes 中的认证(Authentication)以及鉴权(Authorization)机制,其复杂性主要体现在部署 kubernetes 集群时组件之间的认证以及在集群中为附加组件配置正确的权限,希望通过本文让大家可以了解到 kubernetes 中的组件需要哪些权限认证以及如何为相关组件配置正确的权限。
作者简介:😄大家好,我是 Data-Mining(liuzhen007),是一位典型的音视频技术爱好者,前后就职于传统广电巨头和音视频互联网公司,具有丰富的音视频直播和点播相关经验,对 WebRTC、FFmpeg 和 Electron 有非常深入的了解,😄公众号:玩转音视频。同时也是 CSDN 博客专家(博客之星)、华为云享专家(共创编辑、十佳博主)、51CTO 社区编辑、InfoQ 签约作者,欢迎关注我分享更多干货!😄
版权声明: 本文为 InfoQ 作者【liuzhen007】的原创文章。
原文链接:【http://xie.infoq.cn/article/d09de2b68cc88bf40a37e9490】。文章转载请联系作者。
评论