写点什么

揭开 Kubernetes 证书体系的神秘面纱(上)

发布于: 1 小时前
揭开 Kubernetes 证书体系的神秘面纱(上)

【导读】 作为 Kubernetes 的学习/使用者,当你首次搭建/部署 Kubernetes 环境时,生成了一堆证书、Token,还在 kubelet 的配置中用到了 Bootstrap Token,而在安装各种应用时,为了能够与 API Server 通信创建了各种 Service Account,在 Kubectl 中使用了 kubeconfig 登陆;这些内容构成了复杂的证书体系,其中涉及到了哪些认证方式?如何区分用户的?对于初学 Kubernetes 又对密码学一知半解的同学来说,很可能是一道很难逾越的关卡。


本篇文章旨在通过作者自身的学习及工作实践,来揭开 Kubernetes 中证书体系的层层面纱,希望能对正在学习和 Kubernetes 实践过程中有着同样困惑的同学提供一些帮助。


公钥基础设施(PKI)


1.1 CA


CA 是认证中心,证书颁发机构


1.2 CSR

CSR(Certificate Signing Request),它是向 CA 机构申请数字证书时使用的请求文件


注意:CSR 并不是证书。而是向权威证书颁发机构获得签名证书的申请

把 CSR 交给权威证书颁发机构,权威证书颁发机构对此进行签名。

签名后保留好 CSR,当权威证书颁发机构颁发的证书过期的时候,你还可以用同样的 CSR 来申请新的证书,key 保持不变。


1.3 数字证书


数字证书则是由证书认证机构(CA)对证书申请者真实身份验证之后,用 CA 的根证书对申请人的一些基本信息以及申请人的公钥进行签名(相当于加盖证书机构的公章)后形成的一个数字文件。


实际上,(数字)证书最核心内容就是经过 CA 认证过的公钥,除了公钥,还有其他的信息,比如 Email,国家,城市,域名等。



$ openssl x509 -noout -text -in kubeadmin.pem # 数字证书一般以.pem / .crt 结尾Certificate: Data: Version: 3 (0x2) Serial Number: 2c:c7:15:8c:30:e6:4e:4f:81:c8:04 Signature Algorithm: sha256WithRSAEncryption # 签名算法,行有删减 Issuer: C=CN, ST=Beijing, L=Beijing, O=K8S, OU=System, CN=kubernetes # 主体 Validity # 有效时间 Not Before: Sep 7 07:03:00 2020 GMT Not After : Aug 14 07:03:00 2120 GMT Subject: C=CN, ST=Beijing, L=Beijing, O=system:masters, OU=System, CN=admin Subject Public Key Info: # 公钥 Public Key Algorithm: rsaEncryption Public-Key: (2048 bit) Modulus: 00:99:22:04:76:17:4e:38:f2:9d:b0:71:8c:c1:48: Exponent: 65537 (0x10001) X509v3 extensions: # 扩展,可忽略,行有删减 X509v3 Key Usage: critical Digital Signature, Key Encipherment X509v3 Extended Key Usage:
Signature Algorithm: sha256WithRSAEncryption # 数字签名,行有删减 66:9a:9c:97:97:b2:7b:76:2c:45:76:e5:a4:6a:46:4f:a6:4c:
复制代码


1.4 私钥


与公钥算法一起使用的密钥对的秘密一半


  1. 公钥和私钥成对出现

  2. 公开的密钥叫公钥,只有自己知道的叫私钥

  3. 用公钥加密的数据只有对应的私钥可以解密

  4. 私钥签名只有对应的公钥可以验证


证书机制/证书验证


1、证书链信任层次


用一级一级的公钥解开每级的数字签名,一直上溯到可信任的根 CA(ROOT),直到信任根 CA(ROOT),从而验证证书;


  • 客户端获取到了站点证书,拿到了站点的公钥;

  • 要验证站点可信后,才能使用其公钥,因此客户端找到其站点证书颁发者的信息;

  • 站点证书的颁发者验证了服务端站点是可信的,但客户端依然不清楚该颁发者是否可信;

  • 再往上回溯,找到了认证了中间证书商的源头证书颁发者。由于源头的证书颁发者非常少,我们浏览器之前就认识了,因此可以认为根证书颁发者是可信的;

  • 一路倒推,证书颁发者可信,那么它所颁发的所有站点也是可信的,最终确定了我们所访问的服务端是可信的;

  • 客户端使用证书中的公钥,继续完成 TLS 的握手过程。


PKI 与 https 的关系



2.1 TCP 三次握手


  • 客户端向服务端发送带有 SYN 的数据段以及客户端开始发送数据段(Segment)的初始序列号 SEQ

  • 服务端收到数据段时,向客户端发送带有 SYN 和 ACK 的数据段

  • 客户端向服务端发送带有 ACK 的数据段,确认服务端的初始序列号


2.2 TLS 四次握手


  1. 客户端向服务端发送 Client Hello 消息,其中携带客户端支持的协议版本、加密算法、压缩算法以及客户端生成的随机数;

此处信息会包含是否开启 TLS 双向认证,举例如果是 Nginx,则在 conf 中配置 ssl_verify_client on;



  1. 服务端收到客户端支持的协议版本、加密算法等信息后


向客户端发送 Server Hello 消息,并携带选择特定的协议版本、加密方法、会话 ID 以及服务端生成的随机数



b.向客户端发送 Certificate 消息,即服务端的证书链,其中包含证书支持的域名、发行方和有效期等信息

这里服务端会把自己的数字证书发给客户端,客户端会进行证书验证(即验证签发该证书的 CA 是否是权威可信的 CA,客户端本地会放置相同 CA 认证中心的证书,所以判断可信),如果不通过,就会中断握手过程;



c.向客户端发送 Server Key Exchange 消息,传递公钥以及签名等信息



d.向客户端发送可选的消息 CertificateRequest,验证客户端的证书(TLS 双向认证)

e.向客户端发送 Server Hello Done 消息,通知服务端已经发送了全部的相关信息



3.客户端收到服务端的协议版本、加密方法、会话 ID 以及证书等信息后


a.向服务端发送 Client Key Exchange 消息,包含使用服务端公钥加密后的随机数,即预主密钥(Pre Master Secret)

到此客户端和服务端就都拥有了 Random1、Random2 和 Random3,这样两边的秘钥就协商好了,后面数据传输就可以用协商好的秘钥进行加密和解密;



b.向服务端发送 Change Cipher Spec 消息,通知服务端后面的数据段会加密传输,是一条事件消息



c.向服务端发送 Encrypted Handshake 消息,其实对应就是 Message Finished 消息,其中包含加密后的握手信息

客户端将前面的握手消息生成摘要再用协商好的秘钥加密,这是客户端发出的第一条加密消息。服务端接收后会用秘钥解密,能解出来说明前面协商出来的秘钥是一致的;



4.服务端收到 Change Cipher Spec 和 Finished 消息后;


a.向客户端发送 Change Cipher Spec 消息,通知客户端后面的数据段会加密传输


b.向客户端发送 Encrypted Handshake 消息,其实对应就是 Finished 消息,验证客户端的 Finished 消息并完成 TLS 握手


服务端也会将前面的握手过程的消息生成摘要再用秘钥加密,这是服务端发出的第一条加密消息。客户端接收后会用秘钥解密,能解出来说明前面协商出来的秘钥是一致的;



为什么是三个随机数???


"不管是客户端还是服务器,都需要随机数,这样生成的密钥才不会每次都一样。由于 SSL 协议中证书是静态的,因此十分有必要引入一种随机因素来保证协商出来的密钥的随机性。


对于 RSA 密钥交换算法来说,pre-master-key 本身就是一个随机数,再加上 hello 消息中的随机,三个随机数通过一个密钥导出器最终导出一个对称密钥。


pre master 的存在在于 SSL 协议不信任每个主机都能产生完全随机的随机数,如果随机数不随机,那么 pre master secret 就有可能被猜出来(暴力破解),那么仅适用 pre master secret 作为密钥就不合适了,因此必须引入新的随机因素,那么客户端和服务器加上 pre master secret 三个随机数一同生成的密钥就不容易被猜出了,一个伪随机可能完全不随机,可是是三个伪随机就十分接近随机了,每增加一个自由度,随机性增加的可不是一。"


2.3 接下来就真正的到了接口请求的阶段 Application Data,传输内容也是加密的



2.4 最后 Encrypted Alert && Reset


1、客户端 & 服务端发送的,意味着加密通信因为某些原因需要中断,警告对方,不要再发送敏感信息;



2、RST 包用于强制关闭 TCP 链接



承上:PKI 与 Https 关系


Https 与 Kubernetes 的关系:Kubernetes 是通过各种 API 对象来提供不同的功能,访问均是经过 TLS 加密的 https 请求


启下:PKI 与 Kubernetes 关系


PKI 与 Kubernetes 的关系


Kubernetes V1.8 版本后建议开启 TLS 双向认证及 RBAC 授权管理,以加强集群的安全管理,界内流行的开启 TLS 方法为基于一个“公钥基础设施(public key infrastructure,缩写为 PKI)”,使用了内部托管的认证中心(CA)


每个 Kubernetes 集群都有一个集群根证书颁发机构(CA)。集群中的组件通常使用 CA 来验证 API server 的证书,由 API 服务器验证 kubelet 客户端证书等。


为什么 x509 证书会在 k8s 核心组件中广泛使用呢


1.从信息安全的角度来看,x509 证书运用了非对称加密算法(即双钥加密)以及数字签名,相对于使用 password 和 token 方式来讲,更为安全,更难破解


2.从 k8s 认证和授权体系来看,k8s 使用 x509 证书中 CN(Common Name)以及 O(Organization)字段对应 k8s 中的 user 和 group,将 Authentication 和 RBAC 结合到了一起,巧妙地将 Control Plane 中的各个核心 User 和 Group、与操作权限(ClusterRole)进行了绑定(ClusterRoleBinding)


x509 证书与 RBAC 的细节关联,本篇文章暂不做详细介绍


Kubernetes 中的证书逻辑


目前主流版本的 k8s 单集群中,最多存在四条 CA 信任链,而在大多数环境中,则至少需要两条 CA 信任链,即 API Server CA 信任链和 etcd CA 信任链。


apiserver CA 信任链(必要)


etcd CA 信任链(必要)


extension apiserver CA 信任链(非必要,但不可与 API Server 共用 CA 证书)


kubelet CA 信任链(非必要,可并入 API Server CA 信任链



实体证书


证书(通常为 crt 或 pem 扩展名)一般在启动参数中指定


•内嵌证书


证书通过 Base64 转码后,存放于对应组件的 kubeconfig 中,常见于 admin、scheduler、controller manager、kubelet 等组件(用于 Server+Client Auth)


•secrets


常见于 kube-flannel 等组件(Server Auth)


•configmaps


常见于 kube-proxy 等组件(Server Auth),configmaps 中内含 kubeconfig+secrets


4.1 Server Auth


  1. 从架构体系这个维度来看,集群环境中最重要的组件其实就两个—etcd 和 API Server,etcd 作为所有 k8s 中对象的配置信息库,API Server 提供所有组件的 API 访问接口。因而在证书体系中,两者是各需要一套 CA 证书链

  2. 除了 etcd 和 API Server 外,kubelet 在 master 和 node 的通信中,kubelet 也存在的一套 CA 证书链

  3. 另外,默认情况下,API Server 访问 kubelet 时,不需要对 kubelet 进行 Server Auth


4.2 Client Auth


  1. 对于访问 API Server 的其他组件,除了需要确认 API Server 是可信之外(Server Auth),更重要是是向 API Server 证明自己是可信的(Client Auth),因此在很多 API Server 相关组件不同形式的配置参数和文件中,都会见到 Client Certificate 的身影。

  2. 如果存在多集群管理的容器平台,那么该容器平台无论通过 Web API 或者 kubectl 客户端方式访问某个集群的 API Server,都需要将容器平台的 Root CA 证书附加到 API Server 的信任 CA 证书中,否则 API Server 会认为该容器平台是不可信的,容器平台将无法通过 API 访问该集群。


简单来说 ,client 在访问 API Server 时,需要参考以下顺序进行验证工作


1、客户端确认 apiserver 是可信的

如果 Client 证书由该 CA 证书签发,则通过访问请求

2、apiserver 确认客户端是可信的,并对应到用户名

将 client 证书中的 CN—Common Name 和 O—Organization 作为 User 和 Group 字段,用于『3』RBAC 的授权

3、apiserver 确认用户名是否有权操作对应资源

认证 RBAC ,是否有权限操作相对应的资源


4.3 Kubeconfig (内嵌证书) 详细说明


# kubectl config 子命令提供了大部分的参数自动填充kubeconfig文件,分别对应set-cluster、set-credentials、set-contextapiVersion: v1clusters:- cluster: certificate-authority-data: # kubernetes的CA根证书,用于服务器端校验 server: https://xxxk8s.baidu-int.com:6443 # server指定了apiserver的访问地址,是一个负载均衡地址 name: kubernetescontexts: # 可以在kubeconfig里配置多套kubernetes集群,然后使用kubectl的时候就可以指定使用哪个环境,因此1个context就代表1个kubernetes集群- context: cluster: kubernetes user: admin name: admin@kubernetes # 这个context的名字叫做admin@kubernetes,对应集群是kubernetes,用户是admincurrent-context: kubernetes # current-context指定了默认选择的contextkind: Configpreferences: {}users:- name: admin # 这个name仅仅是一个标识,并不代表kubernetes集群中的用户 user: client-certificate-data: # kubernetes签发的客户端证书 client-key-data: # kubernetes签发的客户端证书私钥# 客户端调用apiserver时提交自己的证书给apiserver,那么apiserver将用自己的CA验证客户端证书是否有效,一旦确认有效则完成”认证”,apiserver也就知道了客户端的username
复制代码

4.4 具体的证书逻辑实例


这里将 https、PKI、kubernetes 放在一起,以 API Server & Etcd 交互举例,说明下具体过程:


xx.pem 代表公钥


xx-key.pem 代表私钥


ca.pem 代表根证书



你以为到此就结束了吗?No~


本篇文章中,以 PKI 以及 HTTPS 的相关认证体系为基础,解析了 Kubernetes 内部证书体系中的各层关系,下篇我们将从实际部署/搭建 Kubernetes 的角度出发,详细介绍证书涉及的关键点,敬请期待!


点击进入了解更多技术资讯~~

发布于: 1 小时前阅读数: 2
用户头像

关注百度开发者中心,收获一手技术干货。 2018.11.12 加入

汇聚百度所有对外开放技术、平台和服务资源,提供全方位支持,助力开发者加速成功,实现开发者、消费者和百度三方共赢。https://developer.baidu.com/

评论

发布
暂无评论
揭开 Kubernetes 证书体系的神秘面纱(上)