Kubernetes 客户端认证(二)-- CA 证书的双向认证方式

HTTPS双向认证流程

Kubernetes集群的访问权限控制由 API Server 负责,除了 Token 认证外,还支持 CA 证书 Kubernetes CA 认证也叫HTTPS证书认证,执行 ApiServer CA 认证过滤器链逻辑的前提是客户端和服务端完成 HTTPS 双向认证,下面着重说下 HTTPS 双向认证流程:

  1. 客户端发起建⽴ HTTPS 连接请求,将SSL协议版本的信息发送给服务端;
  2. 服务器端将本机的公钥证书(server.crt)发送给客户端;
  3. 客户端通过自己的根证书(ca.crt)验证服务端的公钥证书(server.crt)的合法性(包括检查数字签名,验证证书链,检查证书的有效期 ,检查证书的撤回状态),取出服务端公钥。
  4. 客户端将客户端公钥证书(client.crt)发送给服务器端;
  5. 服务器端使⽤根证书(ca.crt)解密客户端公钥证书,拿到客户端公钥;
  6. 客户端发送⾃⼰⽀持的加密⽅案给服务器端;
  7. 服务器端根据⾃⼰和客户端的能⼒,选择⼀个双⽅都能接受的加密⽅案,使⽤客户端的公钥加密后发送给客户端;
  8. 客户端使⽤⾃⼰的私钥解密加密⽅案,⽣成⼀个随机数R,使⽤服务器公钥加密后传给服务器端;
  9. 服务端⽤⾃⼰的私钥去解密这个密⽂,得到了密钥 R;
  10. 服务端和客户端在后续通讯过程中就使⽤这个密钥 R 进⾏通信了。

https_ca_authentication.png

注意:默认情况下,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 去访问资源。