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

2021/09/15 11:59
阅读数 295

中国 KubeCon + CloudNativeCon + Open Source Summit 虚拟大会

12 月 9 日至 10 日

https://www.lfasiallc.com/kubecon-cloudnativecon-open-source-summit-china/


诚意邀您成为赞助商





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

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


1. 公钥基础设施(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、证书链信任层次

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


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

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

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

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

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

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


2. PKI 与https 的关系



2.1 TCP 三次握手


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

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

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


2.2 TLS 四次握手


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

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

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

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

    b.向客户端发送 Certificate 消息,即服务端的证书链,其中包含证书支持的域名、发行方和有效期等信息
# 这里服务端会把自己的数字证书发给客户端,客户端会进行证书验证(即验证签发该证书的CA是否是权威可信的CA,客户端本地会放置相同CA认证中心的证书,所以判断可信),如果不通过,就会中断握手过程

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

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

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

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

  1. 向服务端发送 Client Key Exchange 消息,包含使用服务端公钥加密后的随机数,即预主密钥(Pre Master Secret)
    # 到此客户端和服务端就都拥有了Random1、Random2和Random3,这样两边的秘钥就协商好了,后面数据传输就可以用协商好的秘钥进行加密和解密;

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

  3. 向服务端发送Encrypted Handshake消息,其实对应就是 Message Finished 消息,其中包含加密后的握手信息
    客户端将前面的握手消息生成摘要再用协商好的秘钥加密,这是客户端发出的第一条加密消息。服务端接收后会用秘钥解密,能解出来说明前面协商出来的秘钥是一致的

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

  1. 向客户端发送 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 关系


3. 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的细节关联,本篇文章暂不做详细介绍


4. 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 的角度出发,详细介绍证书涉及的关键点,敬请期待!


- End -


重磅!云原生计算交流群成立

扫码添加小助手即可申请加入,一定要备注:名字-公司/学校-地区,根据格式备注,才能通过且邀请进群。


文章转载自百度云原生点击这里阅读原文了解更多


CNCF概况(幻灯片)

扫描二维码联系我们!




CNCF (Cloud Native Computing Foundation)成立于2015年12月,隶属于Linux  Foundation,是非营利性组织。 

CNCF云原生计算基金会)致力于培育和维护一个厂商中立的开源生态系统,来推广云原生技术。我们通过将最前沿的模式民主化,让这些创新为大众所用。请长按以下二维码进行关注。


本文分享自微信公众号 - CNCF(lf_cncf)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

展开阅读全文
加载中

作者的其它热门文章

打赏
0
0 收藏
分享
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部