查看原文
其他

k8s用户安全管理模型简析

洪家铭 云原生社区动态 2022-09-10

作者介绍:洪家铭,就职于谷歌云,Issue Killer。

写这篇文章的动机是,我发现网上对k8s用户安全机制分析的文章几乎都落入对一般人很不友好的两个类别:要么集中介绍k8s使用的某些具体安全协议细节,要么集中介绍k8s中某个安全机制的概念。看了一圈下来总有些只见树木不见森林的感觉。所以,我这篇文章主要是从整体上介绍k8s的安全机制是如何实现的,特别是“信任的链条”是如何传递的。

在一个系统中的安全系统究竟需要完成什么目标?一句话说就是:控制“谁”可以对“什么”做“哪些操作”。其实这句话还隐藏了一个前提,就是安全系统需要能够识别确认一个尝试/正在和系统交互的用户是“谁”。接下的文章就从这个前提入手,介绍k8s的安全模型。

在接下来的阅读前,读者至少需要了解:

•k8s的整体master-worker框架和其中apiServer和etcd的地位和作用(文章1[1],文章2[2])。•k8s中namespace,secret等API资源的概念(文章[3]•非对称加密的应用场景,比如CA证书[4]

1. 发出请求的是谁?

首先需要确定k8s含有哪些身份模型,好比工厂的安保人员对于一个要求开门的请求方可能有如下分类:人类,动物,无人驾驶汽车,对于不同的模型自然有不同的流程去验证。k8s集群中的身份只有两种:用户(User)和服务账号(Service Account)。

为什么需要这两种呢?因为与k8s交互的实际上有两类东西,一是真实的人类,另一个是程序。一个k8s中的user数量一般较少,添加/删除这一类账户往往伴随着人员调动,商业合作等技术之外的变化。而供程序使用的service account则往往数量相对较多,贯穿在整个服务的开发和维护过程中,并且不应该因为人员变化等技术外原因变化。

1.1 用户(User)账户

对于User账户,k8s没有打算附带一套员工管理系统而是采取了极简主义,通过创建k8s集群时自带的管理员(admin)权限(几乎)手动管理master中的凭证文件,并且将每个凭证文件和一个字符串对应起来,只要用户请求中有信息(一般来自本地保存的.kube/config文件中)能够证明自己有任意一个凭证文件的授权,那么这个请求就被认为是一个合法用户发出的,同时这个用户的用户名就是凭证文件对应的字符串。同时,在证书中还可以加入用户所在的组(group)的信息,k8s可以据此认为user在一个组中。

X509客户端证书的一部分:Subject中O(organization)的值代表用户组,CN (common name)代表用户名

凭证文件有三种,分别是X509客户端证书,静态token文件,静态账号密码文件。可以参考这篇文章[5]去详细了解。

user账户管理的本质是管理员将凭证文件和一个字符串对应

1.2 服务账号(Service Account)

Service Account贯穿了服务的开发维护全部流程,比如当有pod需要运行时,必须以一个service account的身份去运行他。这很好理解,一个Pod不应该区分究竟是开发的张三,运维的李四,还是已经离职的王五正在操作自己。由于其重要且常见,k8s提供了创建和管理service account的API,将每一个service account当作一个object存在etcd中。Service account也是像user一样,利用的CA证书进行认证,但是证书保存在etcd,而不是单个文件中。当任何用户或代码可以访问某个serivce account资源时,它们便可以使用etcd中存储的证书以这个service account的名义与apiService交互。

同时重要的一点,service account有namespace这一属性。这很好理解,web和game的namespace中可能都有dev这一个service accout,我们希望可以将同名的service account通过不同的命名空间隔开。但是对于用户(user),前面介绍过k8s只将其对应在一个字符串上而已,可以认为user是全局的。

service account和secret都是储存在etcd中的object

1.3 User与Service Account的关系

这是比较令人疑惑的地方,也是驱使我写这篇文章的最初动力。从前面的介绍看,user和service account两者完全是割裂的:user由凭证文件认证,而service account是一种k8s的api资源。那么当张三使用本地的.kube/config文件作为一个user登录了集群后,他可以使用任意的service account吗?答案肯定是否定的,但是在哪里规定了张三能使用哪些service account呢?换句话说,user是如何与某些service account联系起来的呢?答案是:两者是由一系列存储在etcd中的api资源(Cluster)RoleBinding和(Cluster)Role联系起来的。

service account也是一种资源(resource)。一个(Cluster)Role能否使用某个service account定义在(Cluster)Role.Rules中

举个例子,根据官方文档[6]使用kubeadm创建一个k8s集群,默认账户的状态和配置是怎样的呢?为什么可以使用默认账户以默认service account(default)创建pod呢?我们进行如下探索:

1.首先可以查看登录时使用的证书信息,可以发现context.user=kubernetes-admin2.但是在集群中使用kubectl get rolebindings --all-namespaces 或 kubectl get clusterrolebindings都没有发现相应的用户信息。这时,猜想授权是以用户组的形式发生的而不是单独用户。3.按照前文截图中的方法查看本地证书中的用户组信息,发现Subject: O = system:masters, CN = kubernetes-admin。进一步发现kubectl get clusterrolebindings -o yaml中存在一个binding有.roleRef.name=cluster-admin.subjects[0].kind=Group和 .subjects[0].name=system:masters4.最后使用kubectl get clusterrole cluster:admin查看其权限,发现其拥有所有资源的所有操作权限,包括使用service account运行pod的权限。

cluster-admin拥有所有权限

综上,这个例子中user和service account发生联系的路线为:

1.用户kubernetes-admin属于用户组system:masters (证书中定义)2.用户组system:masters拥有ClusterRole cluster-admin (ClusterRoleBinding中定义)3.ClusterRole中cluster-admin拥有所有service account的使用权限(ClusterRole中定义)

所有和k8s系统的交互都是通过apiServer进行HTTP(S),用户请求到达apiServer后集群会基于以上的方式对请求进行身份认证。

2. “谁”可以对“什么”做“哪些操作”。

当认证完成,“谁”的问题被明确后,后剩下的‘对“什么”做“哪些操作”’就十分简单了。k8s默认拒绝用户(user/service account)的任何操作请求,只有用户通过(cluster)rolebinding拥有的(cluster)role中定义了相应权限,这个请求才会被apiServer认为是合法,进入后续的处理过程。

以上就是用户安全管理模型的简介,在我写这篇文章中还发现了其它一些不错的相关链接,有兴趣的读者可以参考阅读:

•k8s集群各种用户认证方式的详细操作介绍:文章[7]•签发X509证书的具体方法和其他的安全管理简介:文章[8]•什么是JWT(认证方式的一种):文章[9]•Api资源(Cluster)RoleBinding和(Cluster)Role官方文档及示例[10](英文)•对多租户用户行为的进一步安全管理概述:文章[11]

引用链接

[1] 文章1: https://link.zhihu.com/?target=https%3A//www.infoq.cn/article/KNMAVdo3jXs3qPKqTZBw
[2] 文章2: https://zhuanlan.zhihu.com/p/40927470
[3] 文章: https://zhuanlan.zhihu.com/p/115903242
[4] CA证书: https://www.zhihu.com/question/24294477/answer/74783418
[5] 这篇文章: https://zhuanlan.zhihu.com/p/43237959
[6] 官方文档: https://link.zhihu.com/?target=https%3A//kubernetes.io/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/
[7] 文章: https://zhuanlan.zhihu.com/p/97797321
[8] 文章: https://zhuanlan.zhihu.com/p/113853969
[9] 文章: https://link.zhihu.com/?target=https%3A//www.ruanyifeng.com/blog/2018/07/json_web_token-tutorial.html
[10] 官方文档及示例: https://link.zhihu.com/?target=https%3A//kubernetes.io/docs/reference/access-authn-authz/rbac/
[11] 文章: https://zhuanlan.zhihu.com/p/102467110

关于云原生社区

云原生社区是一个有技术、有温度、有情怀的开源社区。由一群开源的狂热爱好者自发成立,秉持“共识、共治、共建、共享”的原则。社区的宗旨是:连接、中立、开源。立足中国,面向世界,企业中立,关注开源,回馈开源。

云原生社区志愿者计划

计划详情请见:云原生社区志愿者招募计划

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存