"認證",形象地理解就是"你是誰"。在上文中,用戶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
在客戶證書文件中,會包含域名/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"
當客戶端使用該認證方式來發起請求的時候,需在Header參數中添加以下字段
Authorization: Bearer <token>
靜態密碼
apiserver可以通過啟動參數--basic-auth-file=/path/to/file來開啟密碼認證,該文件的每一行如下:第一個字段為密碼,第二個為用戶名,第三個為用戶id,后面為組名(可選,如果有多個組,則需要用雙引號引起來)
password,user,uid,"group1,group2,group3"
當客戶端使用該認證方式來發起請求的時候,需在Header參數中添加以下字段
Authorization: Basic <base64encoded(user:password)>
?
?
準備條件
安裝好一個k8s集群,這里我們使用kubeadm安裝好了一個1.17.0的集群,如下
$ kubectl get node
NAME STATUS ROLES AGE VERSION
dcos-160 Ready master 19h v1.17.0
?
?
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"
接著,我們通過以下命令找到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
復制
然后,我們使用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
此時,在當前目錄下就會有如下三個文件
$ ls
client.crt client.csr client.key
然后,使用客戶端證書訪問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"},...
注意,上面的命令在指定client.key與client.crt時一定要寫成相對路徑或絕對路徑,不能寫成以下,否則訪問會報403
$ curl -k --key client.key --cert client.crt https://10.142.232.160