"认证",形象地理解就是"你是谁"。在上文中,用户A在发起API请求时,管理员如何道该请求是用户A发起的呢?所以,客户端在发起API请求时,必须要携带一个身份信息来表明"我是谁",Apiserver在收到请求后,需要对这个身份信息进行认证(“不是你说你是谁,你就是谁,而是我核实你是谁,你才是谁”)

在认证与授权中,有两个重要的概念:用户(USER)与用户组(GROUP)。客户端携带的身份凭证,最终会被apiserver认证为USER与GROUP。

接下来,我们介绍几种常见的认证方式。

X509客户证书

该认证方式下,客户端发起请求时需要携带一个证书,表明自已的身份。该证书必须是由apiserver的启动参数--client-ca-file指定的CA所签发(即能够被该参数指定的CA证书文件所验证)。如果apiserver验证客户端所携带的客户证书是client-ca-file签发的,那么认证通过。

[root@k8s-uat-m01 ~]# cat /etc/kubernetes/manifests/kube-apiserver.yaml | grep ca
    - --client-ca-file=/etc/kubernetes/pki/ca.crt
  • 1.
  • 2.

在客户证书文件中,会包含域名/CN与组织/O字段,假设客户证书的CN为jbeta,组织为app1与app2,那么该请求会被认证为User jbeta与Group app1与app2。

根据上面的理论,客户端在访问apiserver时,需要一个ca.crt来验证apiserver的证书(建立https连接),还需要携带一个client.crt来表明自已的身份。不过在实际中,客户端还需要携带client.key,猜测应该是双向HTTPS的原因

静态Token

apiserver可以通过启动参数--token-auth-file=/path/to/file来开启Token认证。该文件的每一行如下:第一个字段为token,第二个为用户名,第三个为用户id,后面为组名(可选,如果有多个组,则需要用双引号引起来)

token,user,uid,"group1,group2"
  • 1.

当客户端使用该认证方式来发起请求的时候,需在Header参数中添加以下字段

Authorization: Bearer <token>
  • 1.

静态密码

apiserver可以通过启动参数--basic-auth-file=/path/to/file来开启密码认证,该文件的每一行如下:第一个字段为密码,第二个为用户名,第三个为用户id,后面为组名(可选,如果有多个组,则需要用双引号引起来)

password,user,uid,"group1,group2,group3"
  • 1.

当客户端使用该认证方式来发起请求的时候,需在Header参数中添加以下字段

Authorization: Basic <base64encoded(user:password)>
  • 1.

 

 

准备条件

安装好一个k8s集群,这里我们使用kubeadm安装好了一个1.17.0的集群,如下

$ kubectl get node
NAME       STATUS   ROLES    AGE   VERSION
dcos-160   Ready    master   19h   v1.17.0
  • 1.
  • 2.
  • 3.

 

 

X509客户证书

客户证书认证方式,自然需要一个客户端证书。

首先,我们先生成客户端证书对应的key与csr,(注意:由于kubeadm安装的集群授权默认为RBAC,所以下面证书的O要设置为system:masters)

在master节点上执行以下命令

$ openssl genrsa -out client.key 1024
$ openssl req -new -nodes -key client.key -out client.csr -subj "/CN=client/O=system:masters"
  • 1.
  • 2.

接着,我们通过以下命令找到apiserver的--client-ca-file文件,发现为/etc/kubernetes/pki/ca.crt,那么在目录/etc/kubernetes/pki/下还会有一个CA密钥ca.key

$ ps -ef | grep apiserver
root      24752  24707  8 Jan06 ?        01:43:33 kube-apiserver --advertise-address=10.142.232.160 --allow-privileged=true --authorization-mode=Node,RBAC --client-ca-file=/etc/kubernetes/pki/ca.crt --enable-admission-plugins=NodeRestriction --enable-bootstrap-token-auth=true --etcd-cafile=/etc/kubernetes/pki/etcd/ca.crt --etcd-certfile=/etc/kubernetes/pki/apiserver-etcd-client.crt --etcd-keyfile=/etc/kubernetes/pki/apiserver-etcd-client.key --etcd-servers=https://127.0.0.1:2379 --insecure-port=0 --kubelet-client-certificate=/etc/kubernetes/pki/apiserver-kubelet-client.crt --kubelet-client-key=/etc/kubernetes/pki/apiserver-kubelet-client.key --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname --proxy-client-cert-file=/etc/kubernetes/pki/front-proxy-client.crt --proxy-client-key-file=/etc/kubernetes/pki/front-proxy-client.key --requestheader-allowed-names=front-proxy-client --requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.crt --requestheader-extra-headers-prefix=X-Remote-Extra- --requestheader-group-headers=X-Remote-Group --requestheader-username-headers=X-Remote-User --secure-port=6443 --service-account-key-file=/etc/kubernetes/pki/sa.pub --service-cluster-ip-range=10.96.0.0/12 --tls-cert-file=/etc/kubernetes/pki/apiserver.crt --tls-private-key-file=/etc/kubernetes/pki/apiserver.key
  • 1.
  • 2.

复制

然后,我们使用ca.key与ca.crt签署client.csr,得到客户证书文件client.crt

$ openssl x509 -req -days 3650 -in client.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out client.crt
  • 1.

此时,在当前目录下就会有如下三个文件

$ ls
client.crt  client.csr  client.key
  • 1.
  • 2.

然后,使用客户端证书访问apiserver,访问成功

$ curl -k --key ./client.key --cert ./client.crt https://10.142.232.160:6443/api/v1/nodes
{
  "kind": "NodeList",
  "apiVersion": "v1",
  "metadata": {
    "selfLink": "/api/v1/nodes",
    "resourceVersion": "155586"
  },
  ...
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.

注意,上面的命令在指定client.key与client.crt时一定要写成相对路径或绝对路径,不能写成以下,否则访问会报403

$ curl -k --key client.key --cert client.crt https://10.142.232.160
  • 1.