目录
API-server 的作用
API-server 提供的安全机制
认证方式之——TLS
授权方式之——node
授权方式之——RBAC
准入控制之——NodeRestriction
自定义准入插件
API-server 的作用
在 Kubernetes 集群中 API-server 的作用有以下几点:
提供了集群管理的 REST API 接口
提供其他模块之间的数据交互和通信的枢纽
是资源配额控制的入口
提供一定的集群安全机制
通俗来讲,API-server 就是整个集群的入口,任何用户和程序对集群资源的增删改查操作都必须经过 API-server。为了保证集群的安全,API-server 提供了完备的安全机制。
API-server 提供的安全机制
API-server 的本质就是一个 web 服务器,底层代码是基于 go-restful 这个 web 框架搭建的。传统的 web 服务器在安全方面一般都会提供认证/授权机制,以过滤器的方式实现。在 API-server 中也以类似于过滤器的方式提供了认证、授权机制,不同的是 API-server 还提供了准入检查。下面一一讲解。
认证(Authentication),识别用户身份。认证的方式有很多,比如:HTTP base,HTTP token,TLS,Service Account,OpenID Connect 等。高版本的 kubernetes 默认的认证方式是 TLS。在 TLS 认证方案中,每个用户都拥有自己的 X.509 客户端证书,API 服务器通过配置的证书颁发机构(CA)验证客户端证书。
授权(Authorization),识别是否有相应操作权利。授权者,通过组合属性(用户属性,资源属性,实体)的策略向用户授予访问权限。授权的方式也有很多,比如:AlwaysDeny、AlwaysAllow、ABAC、RBAC、node 等,高版本的 kubernetes 默认的授权方式是 RBAC 和 node。
准入(Admission Controller),判断你的操作是否符合集群的要求,这是一种更灵活的管控机制,用户还可以根据自己的需求定义准入插件来管理集群。kubernetes 中将准入模块分为三种,validating(验证型),mutating(修改型)以及两者兼有,准入的默认配置是 NodeRestriction。
我理解的准入和授权的区别主要有以下几点:
运行时机不同。认证/授权模块相当于是 web 开发中的 filter,是针对请求头和证书进行分析操作,运行在具体 handle 处理逻辑之前,而准入模块可以操作具体的请求体,是在具体的处理逻辑中。
管控范围不同。授权模块只管控用户有没有操作的权限,具体操作的细节并不关注。准入模块可以管控用户申请的资源大小(LimitRanger),可以细粒度地划分用户权限(NodeRestriction),可以检查用户创建的命名空间是否存在(NamespaceLifecycle)等等。
运行逻辑不同。准入模块之间是逻辑与的关系,设定之后用户的任何请求必须满足所有的准入检查,如果一个插件不满足就会拒绝请求。认证/授权模块之间是逻辑或的关系,只要满足一个请求就可以通过。
认证方式之——TLS
TLS 是安全传输层协议,包括两部分:TLS 记录协议和 TLS 握手协议。TLS 记录协议主要保证传输过程中信息传输的完整性和私密性,这一部分通过协商后的密钥来加密数据。TLS 握手协议主要是为了认证对方的身份、协商密钥。在握手协议中主要涉及到身份认证,下面结合 Kubernetes 说明。
什么是证书
常见的证书格式是 X509 格式。格式如下:
这个证书里面主要包含了主体的公钥信息,主体的身份信息,证书授权中心,签名信息等等,观察图可知,这个用户组就是 system:nodes,用户名是 system.node.slave1,授权中心是 kubernetes,当需要验证这个证书的真伪时,就需要使用证书授权中心的公钥去解析签名(因为签名是由证书授权中心对证书信息经过消息摘要再使用私钥加密得到的),当解析出来的信息和证书的信息匹配时就认证通过了。
证书授权中心(Certificate Authority)可以自建也可以依赖于第三方机构,本质就是一对密钥,对认证过的身份信息经过私钥加密,公钥公开,任何用户都可以使用公钥解析证书得到被认证者的身份信息,这样就达到了身份验证的目的。
API-server 与 kubelet-client 的证书验证
为了方便用户访问 kube-apiserver,推荐配置方式是采用 kubeconfig 文件。这个配置文件里面描述了集群、上下文和用户信息。我们来看 kubelet 默认的 kubeconfig 文件。
首先 kubelet 的 kubeconfig 如下所示:
上图 users.user.client-certificate 字段就是用户的证书地址,这个证书由 kubernetes 签发,我们使用 kubernetes 的公钥来验证这个文件。
结果显示验证成功,验证成功后得到用户的身份信息。在我们自建 CA 时,一定要保存好 CA 的私钥。如果私钥丢失那么攻击者可以制作证书,从而认证通过。
授权方式之——node
节点授权方式是专门为 kubelet 发出的请求的一种授权方式。从上小节可以看出 kubelet 经过认证以后得到的用户组是 system:nodes,用户名是 system:node:slave1,这个满足节点授权的用户名格式 system:node:<nodename>,于是这个用户被赋予以下的权限。
可见这个节点授权赋予每个节点的权力很大。可以对整个集群的 pod、node 等资源进行操作。如果没有设置准入控制 NodeRestriction,那么节点授权是很危险的。
授权方式之——RBAC
RBAC 是一种基于角色的授权方式,这里涉及到两类资源,一类是 RoleBinding、ClusterRoleBinding,另一类是 Role、ClusterRole,角色是对用户拥有权利的抽象,角色绑定是将角色绑定到用户(user、group 或者 service account)。在使用 RBAC 创建自己的角色时,要秉持最小权限原则,防止操作范围过大而影响集群安全。
在 Kubernetes 中已经默认建立了很多角色,在创建自己的角色之前可以考虑默认的角色。
准入控制之——NodeRestriction
这个插件的作用是限制每一个 kubelet 只能操作自己 node 的资源。在集群部署中,最好设置 NodeRestriction,如果没有设置这个准入插件不法分子可以通过攻克一个子节点获得 kubelet 的证书和密钥,进而远程控制整个集群的资源。
自定义准入插件
Kubernetes 准入模块强大的地方在于提供了 External Admission Webhook,可以基于这个功能自定义准入插件。这里涉及到两个特殊的准入控制器:
MutatingAdmissionWebhook 和 ValidatingAdmissionWebhook。这两个控制器将发送准入请求到外部的 HTTP 回调服务并接收一个准入响应。如果启用了这两个准入控制器,Kubernetes 管理员可以在集群中创建和配置一个 admission webhook。API server 发送一个 AdmissionReview 的 json 数据到 webhook,其中主要包含一个 AdmissionRequest 的请求,以及需要处理的 kubernetes 资源的详细信息。webhook 在接收到该请求之后会根据自定义逻辑进行处理,并返回处理结果 AdmissionResponse。
自定义准入插件的示例代码可以在 github 中找到,这个项目最主要的就是 main.go 文件。
下面是 main.go 文件中的 admit 代码:
这里面核心的结构体就是 AdmissionReview。AdmissionReview 里面的 AdmissionRequest 中封装了可用于逻辑判断的所有请求信息,用户可以根据自己的要求自定义验证逻辑。当创建好自己的镜像之后按照项目中的步骤部署运行。
评论