一、認證、授權、准入控制
kubernetes的安全框架分三層:認證,授權,准入控制
1、認證(authentication):驗證身份,使用證書、用戶名密碼或者token令牌。認證解決用戶是誰的問題。
2、授權(authorization):綁定權限,授權過程,分配到指定空間中。授權解決用戶能做什么的問題。
3、准入控制(admission control):空間准入控制,可以使用下面哪些資源,調用哪些插件,使用插件前先與etcd去驗證,查看etcd是否授權,若是允許,會執行,並將操作記錄到etcd中。准入控制則是資源管理方面的作用。
第一模塊,認證authentication
三種客戶端身份認證
HTTPS證書認證:基於CA證書簽名的數字證書認證
HTTP token 認證:通過一個token來識別用戶——在生產環境中使用廣泛
HTTP base認證:用戶名+密碼的方式認證
K8S集群的證書認證
https://blog.csdn.net/Lfwthotpt/article/details/105892377
httpd的token認證
cat /k8s/cfg/token.csv a031b816095ddada590b24c54a505a9e,kubelet-bootstrap,10001,"system:kubelet-bootstrap"
第二模塊授權——authorization
RBAC(role-based access control,基於角色的訪問控制),負責完成授權(authorization)工作
kubernetes reviews only the following API request attributes:
user——The user string provided during authentication
身份驗證期間提供的用戶字符串
group——the list of group names to which the authenticated user belongs
已驗證用戶所屬的組名列表
extra—— a map of arbitrary string keys to string values,provided by the authentication layer
任意字符串鍵到字符串值的映射,由身份驗證層提供
API——indicates whether the request is for an API resource
指示請求是否針對API資源
request path—— path to miscellaneous non-resource endpoints like /ap1 or /healthz
到其他非資源端點(如/ap1或/healthz)的路徑
api request verb- api verbs get,list,create,update,patch,watch,proxy,redirect,delete,and deletecollection are used for resource requests. To determine the request verb for a resouce api endpoint, see determine the request verb below.
api動詞get、list、create、update、patch、watch、proxy、redirect、delete和deletecollection用於資源請求。要確定resouce api端點的請求謂詞,請參見下面的確定請求謂詞。
http request verb—— http verbs get,post,and delete are used for non-resource requests.
http動詞get、post和delete用於非資源請求。
resource——the id or name of the resouce that is being accessed (for resource requests only) - for resource requests using get,update,patch and delete verbs,you must provide the resource name
正在訪問的資源的id或名稱(僅用於資源請求)——對於使用get、update、patch和delete謂詞的資源請求,您必須提供資源名稱
subresource —— the subresource that is being accessed (for resource requests only)
正在訪問的子資源(僅用於資源請求)
namespace—— the subresource that is being accessed ( for resource requests only)
正在訪問的子資源(僅用於資源請求)
api group —— the api group being accessed (for resource requests only),an empty string designates the core api group
被訪問的api組(僅用於資源請求),一個空字符串指定核心api組
RBAC是基於角色進行控制,所以:
要先創建角色
然后創建要綁定的資源
將角色與目標用戶甚至api和請求等綁定
綁定api模式適用於二次開發
查看apiserver啟用rbac
ps aux | grep apiserver | grep authorization-mod --authorization-mode=Node,RBAC
第三模塊:准入控制(admission control)
admission control 實際上是一個准入控制器插件列表,發送到 api server的請求都需要經過這個列表中的每個准入控制器插件的檢查,檢查不通過,則拒絕請求
–enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,ResourceQuota,NodeRestriction
NamespaceLifecycle: 命令空間回收
LimitRanger:配額管理
ServiceAccount:每個pod中導入方便訪問API
ResourceQuota:基於命名空間的高級配額管理
NodeRestriction:Node加入到K8S集群中以最小權限運行
查看哪些插件是默認啟用的:
kube-apiserver -h | grep enable-admission-plugins
相關的小操作
apiserver使用的是token認證
–enable-bootstrap-token-auth --token-auth-file=/k8s/cfg/token.csv
#ps aux | grep apiserver root 21679 10.2 8.6 1164540 422616 ? Ssl 15:24 8:21 kube-apiserver --advertise-address=192.168.74.132 --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
ServiceAccount
為Pod中的進程和外部用戶提供身份信息,系統賬戶,可以通過serviceaccount在pod中區訪問apiserver
# kubectl get sa NAME SECRETS AGE default 1 7d17h
對外提供的6443端口
#netstat -natp | grep 6443 | grep LISTEN tcp6 0 0 :::6443 :::* LISTEN 21679/kube-apiserve
k8s集群角色超級管理員cluster-admin,擁有所有權限。
kubectl get clusterrole | grep cluster
cluster-admin 2020-11-21T15:35:31Z
#kubectl describe clusterrole cluster-admin
Name: cluster-admin
Labels: kubernetes.io/bootstrapping=rbac-defaults
Annotations: rbac.authorization.kubernetes.io/autoupdate: true
PolicyRule:
Resources Non-Resource URLs Resource Names Verbs
--------- ----------------- -------------- -----
*.* [] [] [*]
[*] [] [*]
二、RBAC 基於角色的訪問控制(Role-Based Access Control )
屬於授權第二階段
RBAC使用rbac.authorization.k8s.io API Group 來實現授權決策,允許管理員通過 Kubernetes API 動態配置策略,要啟用RBAC,需要在 apiserver 中添加參數--authorization-mode=RBAC,如果使用的kubeadm安裝的集群,1.6 版本以上的都默認開啟了RBAC,可以通過查看 Master 節點上 apiserver 的靜態Pod定義文件:
# cat /etc/kubernetes/manifests/kube-apiserver.yaml | grep RBAC
- --authorization-mode=Node,RBAC
如果是二進制的方式搭建的集群,添加這個參數過后,記得要重啟 apiserver 服務。
RBAC API 對象
Kubernetes有一個很基本的特性就是它的所有資源對象都是模型化的 API 對象,允許執行 CRUD(Create、Read、Update、Delete)操作(也就是我們常說的增、刪、改、查操作),比如下面的這下資源:
Pods ConfigMaps Deployments Nodes Secrets Namespaces
上面這些資源對象的可能存在的操作有:
create get delete list update edit watch exec
在更上層,這些資源和 API Group 進行關聯,比如Pods屬於 Core API Group,而Deployements屬於 apps API Group,要在Kubernetes中進行RBAC的管理,除了上面的這些資源和操作以外,我們還需要另外的一些對象:
Rule:規則,規則是一組屬於不同 API Group 資源上的一組操作的集合 Role 和 ClusterRole:角色和集群角色,這兩個對象都包含上面的 Rules 元素,二者的區別在於,在 Role 中,定義的規則只適用於單個命名空間,也就是和 namespace 關聯的,而 ClusterRole 是集群范圍內的,因此定義的規則不受命名空間的約束。另外 Role 和 ClusterRole 在Kubernetes中都被定義為集群內部的 API 資源,和我們前面學習過的 Pod、ConfigMap 這些類似,都是我們集群的資源對象,所以同樣的可以使用我們前面的kubectl相關的命令來進行操作 Subject:主題,對應在集群中嘗試操作的對象,集群中定義了3種類型的主題資源: User Account:用戶,這是有外部獨立服務進行管理的,管理員進行私鑰的分配,用戶可以使用 KeyStone或者 Goolge 帳號,甚至一個用戶名和密碼的文件列表也可以。對於用戶的管理集群內部沒有一個關聯的資源對象,所以用戶不能通過集群內部的 API 來進行管理 Group:組,這是用來關聯多個賬戶的,集群中有一些默認創建的組,比如cluster-admin Service Account:服務帳號,通過Kubernetes API 來管理的一些用戶帳號,和 namespace 進行關聯的,適用於集群內部運行的應用程序,需要通過 API 來完成權限認證,所以在集群內部進行權限操作,我們都需要使用到 ServiceAccount,這也是我們這節課的重點 RoleBinding 和 ClusterRoleBinding:角色綁定和集群角色綁定,簡單來說就是把聲明的 Subject 和我們的 Role 進行綁定的過程(給某個用戶綁定上操作的權限),二者的區別也是作用范圍的區別:RoleBinding 只會影響到當前 namespace 下面的資源操作權限,而 ClusterRoleBinding 會影響到所有的 namespace。
角色: Role——授權特定命名空間的訪問權限 CluserRole——授權所有命名空間的訪問權限 角色綁定 RoleBinding ——將角色綁定到主體(即subject) CluesterRoleBinding ——將集群角色綁定到主體(即subject) 主體(subject) User——用戶賬號 Group——用戶組 ServiceAccount——服務賬號

摘自https://mp.weixin.qq.com/s/awnrscX7VfyLGL0kEi0y1w,一個不錯的運維技術微信公眾號
接下來我們來通過幾個示例來演示下RBAC的配置方法。
我們來創建一個 User Account,只能訪問 kube-system 這個命名空間:
username: zjz group: cetc
第1步:創建用戶憑證
我們前面已經提到過,Kubernetes沒有 User Account 的 API 對象,不過要創建一個用戶帳號的話也是挺簡單的,利用管理員分配給你的一個私鑰就可以創建了,參考https://kubernetes.io/docs/reference/access-authn-authz/authentication/,這里我們來使用OpenSSL證書來創建一個 User,當然我們也可以使用更簡單的cfssl工具來創建:
給用戶 zjz創建一個私鑰,命名成:zjz.key:
# openssl genrsa -out zjz.key 2048 Generating RSA private key, 2048 bit long modulus ..............+++ ....................................+++ e is 65537 (0x10001)
使用我們剛剛創建的私鑰創建一個證書簽名請求文件:zjz.csr,要注意需要確保在-subj參數中指定用戶名和組(CN表示用戶名,O表示組):
# openssl req -new -key zjz.key -out zjz.csr -subj "/CN=zjz/O=cetc"
然后找到我們的Kubernetes集群的CA,我們使用的是kubeadm安裝的集群,CA相關證書位於/etc/kubernetes/pki/目錄下面,如果你是二進制方式搭建的,你應該在最開始搭建集群的時候就已經指定好了CA的目錄,我們會利用該目錄下面的ca.crt和ca.key兩個文件來批准上面的證書請求
生成最終的證書文件,我們這里設置證書的有效期為500天:
# openssl x509 -req -in zjz.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out zjz.crt -days 500
Signature ok subject=/CN=zjz/O=cetc Getting CA Private Key
現在查看我們當前文件夾下面是否生成了一個證書文件:
ls zjz.crt zjz.key zjz.csr
現在我們可以使用剛剛創建的證書文件和私鑰文件在集群中創建新的憑證和上下文(Context):
# kubectl config set-credentials zjz --client-certificate=zjz.crt --client-key=zjz.key User "zjz" set.
我們可以看到一個用戶zjz創建了,然后為這個用戶設置新的 Context:
# kubectl config set-context zjz-context --cluster=kubernetes --namespace=kube-system --user=zjz Context "zjz-context" created.
到這里,我們的用戶zjz就已經創建成功了,現在我們使用當前的這個配置文件來操作kubectl命令的時候,應該會出現錯誤,因為我們還沒有為該用戶定義任何操作的權限呢:
kubectl get pods --context=zjz-context
Error from server (Forbidden): pods is forbidden: User "zjz" cannot list resource "pods" in API group "" in the namespace "kube-system"
第2步:創建角色
用戶創建完成后,接下來就需要給該用戶添加操作權限,我們來定義一個YAML文件,創建一個允許用戶操作 Deployment、Pod、ReplicaSets 的角色,如下定義:(zjz-role.yaml)
# cat zjz-role.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: zjz-role namespace: kube-system rules: - apiGroups: ["", "extensions", "apps"] resources: ["deployments", "replicasets", "pods"] verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] # 也可以使用['*'] 其中Pod屬於 core 這個 API Group,在YAML中用空字符就可以,而Deployment屬於 apps 這個 API Group,ReplicaSets屬於extensions這個 API Group( 我怎么知道的?https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/), 所以 rules 下面的 apiGroups 就綜合了這幾個資源的 API Group:["", "extensions", "apps"],其中verbs就是我們上面提到的可以對這些資源對象執行的操作, 我們這里需要所有的操作方法,所以我們也可以使用['*']來代替。
然后創建這個Role:
kubectl create -f zjz-role.yaml
注意這里我們沒有使用上面的zjz-context這個上下文,因為沒有權限
第3步:創建角色權限綁定
Role 創建完成了,但是很明顯現在我們這個 Role 和我們的用戶 zjz 還沒有任何關系,對吧?這里我就需要創建一個RoleBinding對象,
在 kube-system 這個命名空間下面將上面的 zjz-role 角色和用戶 zjz 進行綁定:(zjz-rolebinding.yaml)
# cat zjz-rolebinding.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: zjz-rolebinding namespace: kube-system subjects: - kind: User name: zjz apiGroup: "" roleRef: kind: Role name: zjz-role apiGroup: ""
上面的YAML文件中我們看到了subjects關鍵字,這里就是我們上面提到的用來嘗試操作集群的對象,這里對應上面的 User 帳號 zjz,使用kubectl創建上面的資源對象:
kubectl create -f zjz-rolebinding.yaml
第4步. 測試
現在我們應該可以上面的haimaxy-context上下文來操作集群了:
# kubectl get pods --context=zjz-context NAME READY STATUS RESTARTS AGE coredns-66bff467f8-gs592 1/1 Running 0 3h36m coredns-66bff467f8-vrk4l 1/1 Running 0 3h36m etcd-master 1/1 Running 0 3h36m kube-apiserver-master 1/1 Running 0 3h36m kube-controller-manager-master 1/1 Running 0 3h36m kube-flannel-ds-amd64-hcsnq 1/1 Running 0 119m kube-flannel-ds-amd64-nwlvk 1/1 Running 0 119m kube-flannel-ds-amd64-pzh5q 1/1 Running 0 119m kube-proxy-2sbdv 1/1 Running 0 3h36m kube-proxy-jj6nh 1/1 Running 0 174m kube-proxy-qr625 1/1 Running 0 175m kube-scheduler-master 1/1 Running 0 3h36m
我們可以看到我們使用kubectl的使用並沒有指定 namespace 了,這是因為我們已經為該用戶分配了權限了,如果我們在后面加上一個-n default試看看呢?
$ kubectl --context=zjz-context get pods --namespace=default Error from server (Forbidden): pods is forbidden: User "haimaxy" cannot list pods in the namespace "default"
https://segmentfault.com/a/1190000021905208 permission-manager 是一個用於 K8s RBAC 和 用戶管理的web工具。
https://mp.weixin.qq.com/s/awnrscX7VfyLGL0kEi0y1w Kubernetes 必須掌握技能之 RBAC
https://mp.weixin.qq.com/s/BWzkem1bJtkuqIYziG_VrA kubernetes認證、授權、准入控制
https://www.cnblogs.com/fuyuteng/p/10984283.html rbac授權
https://blog.csdn.net/lfwthotpt/article/details/106257572 理論+實操:K8S之安全機制——創建相應的權限用戶
https://blog.csdn.net/hy9418/article/details/80268418 k8s UserAccount權限控制
https://www.cnblogs.com/aresxin/p/k8s-sc.html K8S權限控制,限制用戶在多個namespace上的訪問權限
https://blog.csdn.net/wangshui898/article/details/110817257 K8S基礎-鑒權框架與用戶權限分配,總結不錯
