#云原生征文#Kubernetes安全权限管理深度剖析 原创
摘要
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中的组件需要哪些权限认证以及如何为相关组件配置正确的权限。
【本文正在参加云原生有奖征文活动】,活动链接:https://ost.51cto.com/posts/12598