您好,登錄后才能下訂單哦!
K8S 安全機制
一、K8S的安全框架
? 訪問K8S集群的資源需要過三關:認證、鑒權、準入控制
? 普通用戶若要安全訪問集群API Server,往往需要證書、Token或者用戶名+密碼;Pod訪問,比如ingress控制器Ui的Dashboard都需要ServiceAccount,主要是讓這個容器能夠訪問這個API,也就是所有的交互都是通過API的,這可能通過一個人去通過kubectl去交互,也有可能你的程序去調用API,但這些都是需要授權的
? K8S安全控制框架主要由下面3個階段進行控制,每一個階段都支持插件方式,通過API Server配置來啟用插件。
說在前面的話,也就是每個階段都是插件化的設計,可以自己開發插件,把這些集成到步驟里面,來實現相關的訪問控制,這樣的話你就不需要去修改原有的代碼去增加了,所以k8s設計原則有很多都是以擴展性去設計的,都盡可能的讓用戶自定義一些東西,集成到里面。
接下來看一張圖,這是訪問API經歷的一些階段
從上面kubectl、API、UI,訪問的是k8sAPI,k8s的API提供了很多的接口
這些都是Apiserver去提供的,也支持不同的功能,來完成相關的處理的,相關的認證,再往下就是API內置有三層的授權,第一層就是認證,第二層就是鑒權,第三層就是準入控制,然后通過之后就可以訪問相關的資源了,這些資源都是從ETCD中去調用的,一些存儲狀態的信息
傳輸安全:
現在k8s都已經改成https進行訪問,也就是不管你是kubeadm部署還是二進制部署,他都是建議你使用https進行全棧的通信,告別8080,使用6443
認證:
API收到用戶發送的請求之后,他會先認證,認證它這邊有三個可以做到
三種客戶端身份認證:
? HTTPS 證書認證:基于CA證書簽名的數字證書認證,也就是k8s,CA簽出來的證書可以作為你客戶端訪問攜帶的證書,它會幫你認證,這是一種方式,從這個證書里面去提取你有沒有權限去訪問。
? HTTP Token認證:通過一個Token來識別用戶。
? HTTP Base認證:用戶名+密碼的方式認證,這是基于http自身的一個認證,不過這個很少人去用,因為安全系數比較低。
第一關就是標識你是用哪個證書進來的,還是token標識進來的,看看我這里是不是可信任的,看看我這個token我這里有沒有相關的授權,也就是我這里有沒有這個token,如果沒有就不允許通過,然后下面就不會再進行了,如果通過的話,就比如本地已經創建這個token了,有的話就給你放行,進行下一個判斷,也就是第二關授權。
授權:
RBAC(Role-Based Access Control,基于角色的訪問控制):負責完成授權(Authorization)工作。也就是會查看你的訪問符不符合權限,所以它會在這個地方去給你判斷,如果你來的這個身份,雖然有這個身份,但是沒有這個權限訪問這個資源,也會不允許你通過。
授權的資源有很多類型的支持
準入控制:
簡單講就是開發將一些高級的功能,直接插件化的去設計,也就是準入控制器就是一個插件的集合,集合里面就有一些高級的特性,都是以插件去實現的,如果不啟用這些插件的話,那你就使用不了這個功能,這也就是第三關,也就是你的請求會經過你的插件準入控制,準入控制呢會給你效驗請求的實現的這個方法,到底這個插件有沒有啟用這一塊,不過大多數的方式默認的插件都是啟用的,啟動之后來請求相關的資源,才會被允許,因為它啟用插件了,如果沒啟動的話也會不通過
Adminssion Control實際上是一個準入控制器插件列表,發送到API Server的請求都需要經過這個列表中的每個準入控制器,插件的檢查,檢查不通過,則拒絕請求。
1.11版本以上推薦使用的插件:
--enable-admission-plugins= \
NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,ResourceQuota
使用RBAC授權
RBAC(Role-Based Access Control,基于角色的訪問控制),允許通過Kubernetes API動態配置策略。也就是即使配置,即時生效,不需要重啟服務
角色
? Role:授權特定命名空間的訪問權限
? ClusterRole:授權所有命名空間的訪問權限
角色綁定
? RoleBinding:將角色綁定到主體(即subject)
? ClusterRoleBinding:將集群角色綁定到主體
主體(subject)
? User:用戶
? Group:用戶組
? ServiceAccout: 服務賬號
要做一個權限的管理系統,有兩塊,第一塊就是對象是誰,創建的用戶,第二就是權限組,比如創建一個開發組,開發組有哪些權限,可以訪問這個系統,這也是為了方便去管理這些權限,來劃分這個權限組,每個用戶都給他創建一個權限很麻煩,有這個組的話,直接將用戶加入這個組里面就可以了,比如來一個開放,并給他設置權限,他是一個來賓用戶的組,這個組里面只能查看一些東西,但是他是一個開發組的,對一些項目有一些開發權限,管理員進去呢,在這個管理頁面去再去加一個開發組,這樣的話他就有開發組的權限了
K8s和剛才說的其實都是一樣的,用戶就是這個主體,就是誰來訪問,然后權限組呢就是角色,定義了一組權限的集合,用戶要想將用戶與權限集合做一個附加,將開發附加一個權限組,就稱為角色綁定,角色里面又分為了,角色及集群角色,集群角色是授權集群命名空間的,
也就是k8s有命名空間這一說,所以有分為了單個命名空間和所有命名空間,這個權限集合的設置,ClusterRole也就是授權所有命名空間,也就是說將某個用戶加入這個權限角色里,那就意味著它可以訪問所有命名空間,相關的一些權限。
示例:為zhaocheng用戶授權default命名空間Pod讀取權限
比如就是只能查看pod默認的空間的運行的一些資源,像svc,日志是沒有權限查看的,當你試用期過了之后,再給你加一些權限,再做一些相關的操作
實現這個目標需要完成以下三步
創建RBAC權限策略
Ca.crt 和 Ca.key就是這兩個需要簽發的證書
[root@k8s-master ~]# ls /etc/kubernetes/pki/
apiserver.crt apiserver.key ca.crt front-proxy-ca.crt front-proxy-client.key
apiserver-etcd-client.crt apiserver-kubelet-client.crt ca.key front-proxy-ca.key sa.key
apiserver-etcd-client.key apiserver-kubelet-client.key etcd front-proxy-client.crt sa.pub
[root@k8s-master ~]# cd demo/
[root@k8s-master demo]# mkdir rbac
[root@k8s-master demo]# cd rbac/
[root@k8s-master rbac]# rz -E
rz waiting to receive.
[root@k8s-master rbac]# ls
cert.sh cfssl.sh config.sh rbac.yaml
[root@k8s-master rbac]# cat cfssl.sh
wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64
wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64
wget https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64
chmod +x cfssl*
mv cfssl_linux-amd64 /usr/bin/cfssl
mv cfssljson_linux-amd64 /usr/bin/cfssljson
mv cfssl-certinfo_linux-amd64 /usr/bin/cfssl-certinfo
[root@k8s-master rbac]# sh cfssl.sh
然后這里我們把我們證書簽發的腳本拿過來,這里注意的是簽發用戶的CN這里是指簽發用戶的用戶名,就是說k8s拿這個CA來認證,它不單效驗是不是我頒發的證書,還要效驗里面的用戶名,就是CN這個字段是不是授權過的,相當于鑒權那一塊,O是用戶組,也可以基于這個用戶組去做這個權限限制
[root@k8s-master rbac]# chmod +x cert.sh
[root@k8s-master rbac]# vim cert.sh
cat > ca-config.json <<EOF
{
"signing": {
"default": {
"expiry": "87600h"
},
"profiles": {
"kubernetes": {
"usages": [
"signing",
"client auth"
],
"expiry": "87600h"
}
}
}
}
EOF
cat > zhaocheng-csr.json <<EOF
{
"CN": "zhaocheng",
"hosts": [],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "BeiJing",
"L": "BeiJing",
"O": "k8s",
"OU": "System"
}
]
}
EOF
cfssl gencert -ca=/etc/kubernetes/pki/ca.crt -ca-key=/etc/kubernetes/pki/ca.key -config=ca-config.json -profile=kubernetes zhaocheng-csr.json | cfssljson -bare zhaocheng
[root@k8s-master rbac]# bash cert.sh
主要生成的就是zhaocheng-key.pem zhaocheng.pem
[root@k8s-master rbac]# ls
ca-config.json cert.sh cfssl.sh config.sh rbac.yaml zhaocheng.csr zhaocheng-csr.json zhaocheng-key.pem zhaocheng.pem
需要用這兩個證書來對客戶端做請求認證,寫到客戶端授權文件里,用這個授權文件就能請求這個k8s集群了
比如公司有多個集群,那么這個開發需要登錄這個集群,需要這個config證書,到時候可以拿這個來回切換登錄不同的集群
--kubeconfig=zhaocheng.kubeconfig
[root@k8s-master rbac]# vim config.sh
kubectl config set-cluster kubernetes \
--certificate-authority=/etc/kubernetes/pki/ca.crt \
--embed-certs=true \
--server=https://192.168.30.21:6443 \
--kubeconfig=zhaocheng.kubeconfig
設置客戶端認證
kubectl config set-credentials zhaocheng \
--client-key=zhaocheng-key.pem \
--client-certificate=zhaocheng.pem \
--embed-certs=true \
--kubeconfig=zhaocheng.kubeconfig
設置默認上下文
kubectl config set-context kubernetes \
--cluster=kubernetes \
--user=zhaocheng \
--kubeconfig=zhaocheng.kubeconfig
設置當前使用配置
kubectl config use-context kubernetes --kubeconfig=zhaocheng.kubeconfig
[root@k8s-master rbac]# bash config.sh
[root@k8s-master rbac]# cat zhaocheng.kubeconfig
現在就可以拿這個kubeconfig去訪問集群了
到這呢其實是到認證這個地方給打回去了,node節點是沒有訪問權限的,已經識別出來是zhaocheng用戶了,但是鑒權這塊沒有相關的授權,所以現在要為這個用戶授權
[root@k8s-master rbac]# kubectl get --kubeconfig=./zhaocheng.kubeconfig node
Error from server (Forbidden): nodes is forbidden: User "zhaocheng" cannot list resource "nodes" in API group "" at the cluster scope
如果有一個組的命名空間,權限比較大,就是可以訪問所有命名空間,比如運維來講,有很多的運維,可以創建集群的角色,這樣它是管控所有命名空間的角色,這個角色就是針對于特定的命名空間的,比如開發,測試,它只能訪問命名空間的項目,它負責的項目,然后可以使用這個指定命名空間,然后就是集群的綁定,然后綁定到zhaocheng這個用戶身上,這里我定義的是user,也可以是group組。
pod也是不能訪問的
[root@k8s-master rbac]# kubectl get --kubeconfig=./zhaocheng.kubeconfig pod
Error from server (Forbidden): pods is forbidden: User "zhaocheng" cannot list resource "pods" in API group "" in the namespace "default"
[root@k8s-master rbac]# vim rbac.yaml
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: default
name: pod-reader
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "watch", "list"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: read-pods
namespace: default
subjects:
- kind: User
name: zhaocheng
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io
[root@k8s-master rbac]# kubectl create -f rbac.yaml
然后現在就可以進行訪問了
[root@k8s-master rbac]# kubectl get --kubeconfig=./zhaocheng.kubeconfig pod
NAME READY STATUS RESTARTS AGE
my-pod 1/1 Running 0 10h
nfs-744d977b46-dh9xj 1/1 Running 0 29h
nfs-744d977b46-kcx6h 1/1 Running 0 29h
nfs-744d977b46-wqhc6 1/1 Running 0 29h
nfs-client-provisioner-fbc77b9d4-kkkll 1/1 Running 0 11h
nginx-797db8dc57-tdd5s 1/1 Running 0 8h
nginx-a1-6d5fd7b8dd-w647x 1/1 Running 0 4h65m
nginx-statefulset-0 1/1 Running 0 7h7m
nginx-statefulset-1 1/1 Running 0 7h7m
nginx-statefulset-2 1/1 Running 0 7h7m
web-0 1/1 Running 0 4h65m
web-1 1/1 Running 0 4h63m
web-2 1/1 Running 0 4h62m
但是svc是沒有定義的所以還不能訪問
[root@k8s-master rbac]# kubectl get --kubeconfig=./zhaocheng.kubeconfig svc
Error from server (Forbidden): services is forbidden: User "zhaocheng" cannot list resource "services" in API group "" in the namespace "default"
比如我們加一個別的訪問權限,比如service,deployment
在剛才我們的rbac的策略里面加上這些權限
- apiGroups: [""]
resources: ["pods","services"]
verbs: ["get", "watch", "list"]
再來測試一下,已經可以正常去訪問svc了
[root@k8s-master rbac]# kubectl get --kubeconfig=./zhaocheng.kubeconfig service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.1.0.1 <none> 443/TCP 30h
my-service ClusterIP None <none> 80/TCP 7h32m
nginx ClusterIP None <none> 80/TCP 4h69m
service NodePort 10.1.207.32 <none> 80:30963/TCP 8h
zhao ClusterIP 10.1.75.232 <none> 80/TCP 7h41m
zhaocheng ClusterIP 10.1.27.206 <none> 80/TCP 7h43m
像其他的授權可以查看官方提供
https://kubernetes.io/docs/reference/access-authn-authz/rbac/
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。