Kubernetes 客户端认证(二)-- CA 证书的双向认证方式
HTTPS双向认证流程
Kubernetes集群的访问权限控制由 API Server 负责,除了 Token 认证外,还支持 CA 证书 Kubernetes CA 认证也叫HTTPS证书认证,执行 ApiServer CA 认证过滤器链逻辑的前提是客户端和服务端完成 HTTPS 双向认证,下面着重说下 HTTPS 双向认证流程:
- 客户端发起建⽴ HTTPS 连接请求,将SSL协议版本的信息发送给服务端;
- 服务器端将本机的公钥证书(server.crt)发送给客户端;
- 客户端通过自己的根证书(ca.crt)验证服务端的公钥证书(server.crt)的合法性(包括检查数字签名,验证证书链,检查证书的有效期 ,检查证书的撤回状态),取出服务端公钥。
- 客户端将客户端公钥证书(client.crt)发送给服务器端;
- 服务器端使⽤根证书(ca.crt)解密客户端公钥证书,拿到客户端公钥;
- 客户端发送⾃⼰⽀持的加密⽅案给服务器端;
- 服务器端根据⾃⼰和客户端的能⼒,选择⼀个双⽅都能接受的加密⽅案,使⽤客户端的公钥加密后发送给客户端;
- 客户端使⽤⾃⼰的私钥解密加密⽅案,⽣成⼀个随机数R,使⽤服务器公钥加密后传给服务器端;
- 服务端⽤⾃⼰的私钥去解密这个密⽂,得到了密钥 R;
- 服务端和客户端在后续通讯过程中就使⽤这个密钥 R 进⾏通信了。
注意:默认情况下,HTTPS 是先进行 TCP 三次握手,再进行 TLS 四次握手。
API Server配置
以 kubeadm 为例,使用 Kubeadm 初始化的 Kubernetes 集群中,API Server 是以静态 Pod 的形式运行在 Master Node 上。 可以在 Master Node 上找到其定义文件/etc/kubernetes/manifests/kube-apiserver.yaml,部分启动命令参数部分如下:
spec:
containers:
- command:
- kube-apiserver
- --client-ca-file=/etc/kubernetes/pki/ca.crt
- --tls-cert-file=/etc/kubernetes/pki/apiserver.crt
- --tls-private-key-file=/etc/kubernetes/pki/apiserver.key
API Server 作为服务端时,需要有如下三个启动参数:
--client-ca-file
: 指定 CA 根证书文件为/etc/kubernetes/pki/ca.crt,内置 CA 公钥用于验证某证书是否是 CA 签发的证书,Kubectl 和 Kube-Apiserver 之间认证的话,ca.crt 用于验证 Kubectl 的客户端证书是否是 CA 签发的证书。--tls-cert-file
:指定 Kube-Apiserver 证书文件为/etc/kubernetes/pki/apiserver.crt--tls-private-key-file
: 指定 Kube-Apiserver 私钥文件为/etc/kubernetes/pki/apiserver.key
创建 opt 用户和 CA 证书
接下来以在系统上创建一个 opt 用户,和在 kubernetes 上创建一个 opt 用户为例子,示例说明在如何通过创建用户和创建证书,并使用证书来访问 kubernetes。
系统上创建 opt 用户
在系统上创建 opt 用户,并创建 .kube 目录:
useradd -d /home/opt opt
mkdir /home/opt/.kube
kubernetes 创建 ServiceAccount 用户
通过 ServiceAccount 创建 opt 用户:
kubectl create serviceaccount opt -n kube-system
kubernetes 对 ServiceAccount 进行 RBAC 授权
使用 RBAC 创建规则,使 opt 用户可以访问资源。比如这里所以 admin 权限 default 这个 namespace:
kubectl create rolebinding opt-admin-binding --clusterrole=admin --user=opt --namespace=default
使用 CA 根证书生成 opt 用户私钥和证书
客户端要通过 HTTPS 证书双向认证的形式访问 ApiServer 需要生成客户端的私钥和证书,其中客户端证书的在生成时-CA
参数要指定为 ApiServer 的 CA 根证书文件/etc/kubernetes/pki/ca.crt,-CAkey
参数要指定为 Api Server 的 CA key 文件/etc/kubernetes/pki/ca.key。
创建客户端私钥
以生成一个 opt 用户证书为例,生成用户的私钥:
openssl genrsa -out opt.key 2048
创建证书签署请求
基于客户端私钥生成客户端证书的签名请求文件 opt.csr,其中 CN 代表 kubernetes 用户,O 代表 kubernetes 组:
openssl req -new -key opt.key -subj "/CN=opt/O=kubernetes" -out opt.csr
签署证书
基于证书请求文件、根 CA 证书、根 CA 私钥生成客户端证书,并设置有效期为 10 年:
openssl x509 -req -in opt.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out opt.crt -days 3650
验证证书
验证客户端证书 opt.crt 是由 ca.crt 签发:
# openssl verify -CAfile /etc/kubernetes/pki/ca.crt opt.crt
opt.crt: OK
查看查看证书有效期:
# openssl x509 -in opt.crt -noout -dates
notBefore=Sep 6 16:33:29 2024 GMT
notAfter=Sep 4 16:33:29 2034 GMT
查看证书拥有者信息:
# openssl x509 -in opt.crt -noout -subject
subject=CN = opt, O = kubernetes
测试访问
通过 curl 使用生成的用户端私钥和证书,测试访问 ApiServer:
# curl --cert opt.crt --key opt.key --cacert /etc/kubernetes/pki/ca.crt https://192.168.0.2:6443/api
{
"kind": "APIVersions",
"versions": [
"v1"
],
"serverAddressByClientCIDRs": [
{
"clientCIDR": "0.0.0.0/0",
"serverAddress": "192.168.0.2:6443"
}
]
}
测试能正常访问后,可以设置到 config 文件中方便实用。
设置 kubeconfig 文件
设置集群
设置一个名为 kubernetes 的集群名字:
kubectl config set-cluster kubernetes --server=https://192.168.0.2:6443 --embed-certs=true --certificate-authority=/etc/kubernetes/pki/ca.crt --kubeconfig=/home/opt/.kube/config
将用户详细信息添加到配置文件中
将客户端证书文件 opt.crt 和客户端密钥文件 opt.key 设置为名为 opt 的用户凭证,并将这些证书和密钥嵌入到 kubeconfig 文件中:
kubectl config set-credentials opt --embed-certs=true --client-key=opt.key --client-certificate=opt.crt --kubeconfig=/home/opt/.kube/config
将上下文详细信息添加到配置文件中
为集群和 opt 用户配置 kubeconfig 文件中:
kubectl config set-context opt@kubernetes --cluster=kubernetes --user=opt --kubeconfig=/home/opt/.kube/config
设置用户上下文
给 opt 用户设置上下文环境:
kubectl config use-context opt@kubernetes --kubeconfig=/home/opt/.kube/config
现在当 opt 用户输入 kubectl
命令时,相应动作会应用于 opt@kubernetes 上下文中所列的集群和名字空间。 同时,命令会使用 opt 上下文中所列用户的凭证。
使用 kubeconfig 文件
把/home/opt/.kube
目录更改权限为 opt 用户使用:
chown -R opt:opt /home/opt/.kube/
后面系统上的 opt 用户便可以通过 kubernetes 的 opt 用户使用 kubectl 去访问资源。