k8s許可權管理(RBAC)

q_7發表於2024-05-25

1:安全認證

1、訪問控制概述

  1. 客戶端
    • useraccount,一般是獨立於k8s之外的其他服務管理的使用者賬號
    • serviceaccount,k8s管理的賬號,用於為pod中的服務程序在訪問k8s時提供身份標識

服務賬戶:

  • service account adminsion controller:
    • 對於pod進行修改,建立

img
img

  1. 授權裁決
    • api請求的k8s授權在api伺服器內進行,api伺服器根據所有策略評估所有的請求屬性,然後允許或拒絕請求
    • api的請求的所有部分,都必須透過某種授權來允許機制以便繼續訪問,預設情況下拒絕訪問

2、核心概念

1、角色(Role)與叢集角色(ClusterRole)

用於定義對資源的訪問許可權

  1. 角色(Role)---名稱空間下的許可權的設定(增刪改查)

    • role是一種kubernetes物件,它定義了特定名稱空間內資源的一組許可權,這些許可權可以是建立,讀取,更新和刪除等操作,針對特定的API資源物件(Pod,Service,CongifMap等)

    • role物件只在特定的名稱空間內生效,即它定義的許可權只適用於該名稱空間內的資源

  2. 叢集角色(ClusterRole)---對於整個叢集的許可權的設定

    • ClusterRole也是一種k8s物件,與Role類似,但是作用的範圍更廣泛,可以應用於整個叢集,而不限於特定的名稱空間

    • ClusterRole定義了對叢集範圍內的資源的許可權,可以包括所有名稱空間中資源,也可以包含叢集級別的資源,例如,節點,名稱空間等

  3. 二者的區別

    • role的作用範圍只有對名稱空間,而ClusterRole作用的與整個叢集的資源
      img

2、角色繫結(RoleBinding)與叢集角色繫結(ClusterRoleBinding)

在kubernetes中,角色繫結和叢集角色繫結用於將使用者,組,或服務賬戶與角色或叢集角色關聯起來,從而賦予他們相應的許可權,他們的作用就是將許可權分配給特定的實體,使其能夠執行定義在角色或叢集角色中的操作

  1. 角色繫結(RoleBinding)

    • RoleBinding是一種kubernetes物件,用於將特定的角色(role)與特定的使用者,組,或者服務賬戶繫結在一起,從而賦予他們在某個名稱空間內的資源上執行操作的許可權

    • 例如,可以建立一個RoleBinding,將角色(editor)與使用者alice繫結在一起,這樣alice就具有在特定名稱空間內編輯資源的許可權

  2. 叢集角色繫結(ClusterRoleBinding)

    • 作用範圍更加的廣,將叢集角色與使用者,組,服務賬戶繫結在一起,賦予他們在整個叢集範圍內執行操作的許可權

    • 例如,可以建立一個ClusterRoleBind,將叢集角色管理員(ClusterAdmin)與使用者組"管理員組"繫結在一起,這樣管理員組就具有在整個叢集中執行管理員操作的許可權

  3. 透過角色繫結,kubernetes管理員可以靈活的控制不同使用者,組,服務賬戶對叢集資源的訪問許可權,從而實現安全的許可權管理
    img

3、主體(Subject)

在kubernetes中,主體(Subject)是具有身份的實體,通常是使用者,組,或服務賬戶,主體透過角色繫結或者叢集角色繫結與角色或者叢集角色關聯在一起,從而獲取對kubernetes資源的訪問許可權

  1. 主體

    • 使用者:k8s中與外部身份驗證服務整合,以允許使用基於使用者和密碼的身份驗證機制登入到叢集中,登入成功後,使用者被視為主體,並根據被分配角色獲得相應的許可權

    • 組:在某些情況下,將一組使用者組織在一起,並且為整個組分配許可權可能更加的方便,不用一個一個的使用者分配許可權,他們加入到一個組中,然後對於這個組分配許可權;可以透過角色繫結或叢集角色繫結將組與角色或者叢集角色關聯起來,從而將許可權分配給組內的所有成員,快捷

    • 服務賬戶:服務賬戶是k8s一種特殊型別的身份,用於表示正在執行的容器或pod,他們通常用於實現應用程式和其他k8s部署的自動化任務,通常為服務賬戶分配適當的角色或叢集角色,可以確保他們具有執行操作所需的許可權

  2. 總之

    • 主體在k8s中代表了具有身份的實體,透過角色繫結,或叢集角色繫結相關聯,從而獲得對k8s資源的訪問許可權

3、RBAC在k8s中實現

1、k8s api server與RBAC元件

kubernetes api server與RBAC元件之間實現認證授權機制過程如下

  1. 認證(Authentication)
    • 當使用者或服務向api server發起請求時,首先會經過認證階段,認證過程驗證請求的身份是否合法,並確定請求的發起者是誰,哪一個主體(使用者,組,服務賬戶)

    • k8s支援多種認證方式,包括基本驗證,客戶端證書認證,Token認證等,使用者可以根據需求選擇適合的認證方式

    • 認證成功後,api server將為請求分配一個身份標識,用於後續的操作

  2. 授權(Authorization)---流程
    • 在認證成功後,api server 會將請求與RBAC規則進行匹配,以確定請求是否被允許執行,這個過程被稱為授權

    • RBAC規則由Role,ClusterRole,RoleBinding和ClusterRoleBinding定義,用於描述使用者,組或服務賬戶在叢集中的訪問許可權

    • 當請求達到API server後,api server會將請求中包含的身份資訊,以及RBAC規則中定義的許可權來決定是否允許執行請求所涉及的操作

    • 如果請求的身份與RBAC規則匹配且有足夠的許可權,則api server授權請求執行操作,否則,請求被拒絕,並返回相應的錯誤資訊

  3. 總之
    • 綜上所述,api server與RBAC元件之間實現認證授權機制過程包括認證和授權2個階段,認證階段用於驗證請求的身份,確定請的發起者是誰;授權階段則用於根據RBAC規則檢查請求的許可權,決定是否執行執行操作,這個2個階段共同構成了k8s的訪問控制機制, 確保請求的合法性和安全性
      img

2、RBAC許可權檢查流程

RBAC(基於角色的訪問控制),在k8s中許可權檢查流程如下

  1. 認證

    • 使用者或服務透過身份驗證機制(證書,令牌等)與api server建立連線
  2. 授權:一但使用者或服務透過認證,api server對請求的進行授權檢查,授權檢查的過程包括以下步驟

    • 識別主體,api server根據認證資訊識別請求的主體,即傳送請求的使用者,服務或實體

    • 確定請求的操作和目標資源,api server解析請求中包含的操作(例如,get,post,delete等)和目標資源(pod,deploy等)

    • 查詢RBAC規則,api server根據主體和請求的操作的資源,查詢與之相關的RABC規則,這些規則通常儲存在叢集中的role,ClusterRole,rolebinding和clusterrolebinding中

    • 匹配規則,api server會將查詢到的規則與請求的進行匹配,如果存在請求匹配的規則,則請求被授權執行,否則,請求被拒絕

  3. 執行請求:如果請求同構了授權檢查,api server將hi執行請求所代表的操作,列如建立,更新,刪除資源等

  4. 透過以上的流程,RBAC系統實現了對使用者和服務細粒度訪問控制,確保只有經過授權的和服務才能執行特定的操作
    img

img

2、操作

1、Role資源的編寫

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
   name: pod-reader   #角色的名稱
   namespace: dev     #名稱空間的許可權設定
rules:
- apiGroups: [""]  #管理的資源組
  resources: ["pods"]   #具體的資源
  verbs: ["get","list"]   #具體的操作

#rule只能對於一個名稱空間設定許可權,然後賦予使用者的,這個使用者對於這名稱空間的話,就只有get,list的許可權了

#其餘的資源的編寫跟這個一樣,

3、建立普通使用者和服務賬戶

1、建立普通使用者

原理:透過建立證書和切換上下文環境的方式來建立和切換使用者

#建立證書
##建立私鑰
[root@master ~]# openssl genrsa -out devuser.key 2048
##利用私鑰建立一個csr(證書請求)檔案
openssl req -new -key devuser.key -subj "/CN=devuser" -out devuser.csr

##私鑰加上請求檔案生成證書
openssl x509 -req -in devuser.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out devuser.crt -days 365


#生成賬號
[root@master ~]#  kubectl config set-credentials devuser --client-certificate=./devuser.crt --client-key=./devuser.key --embed-certs=true
User "devuser" set.

#設定上下文引數,這裡設定名稱空間沒有直接的關係,並不是這個使用者只能在這個名稱空間下面操作,其他的空間也可以,要設定許可權
kubectl config set-context devuser@kubernetes --cluster=kubernetes --user=devuser --namespace=dev

#檢視上下文
[root@master ~]#  kubectl config get-contexts
CURRENT   NAME                          CLUSTER      AUTHINFO           NAMESPACE
          devuser@kubernetes            kubernetes   devuser            dev
*         kubernetes-admin@kubernetes   kubernetes   kubernetes-admin   

#切換為建立的使用者的上下文環境中
[root@master ~]# kubectl config use-context devuser@kubernetes
Switched to context "devuser@kubernetes".
#發現看不了,因為沒有設定這個使用者的相關的許可權
[root@master ~]# kubectl get pod -n dev
Error from server (Forbidden): pods is forbidden: User "devuser" cannot list resource "pods" in API group "" in the namespace "dev"

#對賬號進行授權,先切換回來
kubectl config use-context kubernetes-admin@kubernetes

#授權檔案
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
   name: devuser-role
   namespace: dev
rules:
- apiGroups: ["*"]
  resources: ["pods"]
  verbs: ["list"]  #這裡只設定了list這個許可權,就是檢視名稱空間下面的所有資源

---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
   name: devuser-rolebinding
   namespace: dev
subjects:
- kind: User
  name: devuser
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: devuser-role
  apiGroup: rbac.authorization.k8s.io


[root@master role]# kubectl create -f devuser.yaml 
role.rbac.authorization.k8s.io/devuser-role created
rolebinding.rbac.authorization.k8s.io/devuser-rolebinding created


#切換到建立的新使用者上面,切換上下檔案環境
#發現只有獲取這個名稱空間下面資源的許可權,其餘的許可權都沒有賦予
[root@master role]# kubectl config use-context devuser@kubernetes
Switched to context "devuser@kubernetes".
[root@master role]# kubectl get pod -n dev
NAME     READY   STATUS    RESTARTS   AGE
centos   1/1     Running   0          21h
[root@master role]# kubectl delete pod -n dev centos
Error from server (Forbidden): pods "centos" is forbidden: User "devuser" cannot delete resource "pods" in API group "" in the namespace "dev"

2、建立組

建立組與與建立使用者一樣
只不過是yaml檔案格式有一點區別而已,就是kind這裡注意一下即可
ubjects:
- kind: User
  name: my-user
- kind: Group
  name: my-group    # 將使用者新增到組中,有多個話,也這樣新增即可

3、建立服務賬戶

  1. 是一種身份驗證和授權的機制,用於k8s叢集內部進行服務間通訊和資源訪問的身份的認證

  2. k8s中每個pod都有一個服務賬戶相關聯,預設的情況下,pod使用其所屬名稱空間中預設服務賬戶(建立一個名稱空間,預設會建立一個default的服務賬戶),服務賬戶透過為pod分配身份,使其能夠與api 進行互動並訪問其他的資源

[root@master pod]# kubectl describe  pod -n dev centos  | grep -i service
Service Account:  default   #預設是這個賬戶
  1. 適用的場景

    • pod需要與api互動,獲取或修改資源的資訊,獲取自己和別人的資訊,還能修改,只要有足夠的許可權

    • pod需要訪問其他的k8s資源,configmap,secret或者其他的pod

    • pod需要執行某些身份認證的操作,例如透過serviceaccount獲取其他的api資源

  2. 詳細的介紹

    • service account服務賬戶是給執行在pod裡面程式使用的身份認證,pod裡面的程序需要訪問api server時,用的就是service account賬戶

    • service account僅侷限在namespace,只有該namespace下的pod引用這個service account才有許可權,然後關聯這個secret,這個裡面有service account的相關資訊(token,ca,等),訪問api server時用的token,ca,這些資訊都會被掛載到容器裡面去

#這些secret裡面的資訊就會掛載到容器裡面,這些就是server account憑證,
#就是容器啟動後都會掛載對應的service account引用的token,namespace,ca這些
[root@centos /]# cd /var/run/secrets/kubernetes.io/serviceaccount
[root@centos serviceaccount]# ls
ca.crt	namespace  token

#思路就是這個pod訪問api server獲取一些資源,然後驗證它是什麼身份,然後這個身份繫結了什麼樣的許可權,能否執行這樣的操作
  • 如果pod不指定的service account,就會自動的引用預設的service account.這樣就能訪問api server
  1. 注意
    • 在名稱空間中建立Pod的時候,不指定pod所用的service account將會預設使用預設的serviceaccount(也就是預設名稱空間下面有一個服務賬戶)

    • service account為服務提供了一種方便的認證機制,但是service account不關心授權問題,pod繫結了service account之後,僅僅是能夠訪問api server了,但是能訪問api server中的哪些資源了(pod,deploy,configmap)需要配合RBAC來為service account授權,


#建立一個service account
[root@master pod]# kubectl create serviceaccount -n dev t1
serviceaccount/t1 created

#建立一個sercret並且關聯到這個server account
[root@master serviceaccount]# kubectl create -f s1-secret.yaml 
secret/s1-secret created
[root@master serviceaccount]# cat s1-secret.yaml 
apiVersion: v1
kind: Secret
metadata:
   name: s1-secret
   namespace: dev
type: Opaque
data:
  username: czE=
  password: MTIz

#對於這個service account(t1)不進行授權的操作
#建立一個pod,關聯到t1賬戶上面去
[root@master serviceaccount]# cat s1-pod.yaml 
apiVersion: v1
kind: Pod
metadata:
   name: s1-pod
   namespace: dev
spec:
   serviceAccountName: s1
   containers:
   - name: centos
     image: centos
     imagePullPolicy: IfNotPresent
     command: ["/bin/bash","-c","while true;do sleep 3600;done"]

[root@master serviceaccount]# kubectl create -f s1-pod.yaml 
pod/s1-pod created

#這個pod繫結到service account上面去了
[root@master serviceaccount]# kubectl describe  pod -n dev s1-pod  | grep -i service
Service Account:  s1
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-hpccw (ro)

#進入這個容器裡面進行訪問api server
[root@master serviceaccount]# kubectl exec -ti -n dev s1-pod -n dev -- /bin/bash
[root@s1-pod /]# ls
##檢視這個secret資訊掛載到這個pod裡面去了,訪問api server時,拿著這些東西進行驗證登操作,透過https的請求訪問apiserver了
[root@s1-pod ~]# cd /var/run/secrets/kubernetes.io/serviceaccount
[root@s1-pod serviceaccount]# ls
ca.crt	namespace  token

#發現沒有許可權
[root@s1-pod serviceaccount]# curl --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt --header "Authorization:Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_SERVICE_PORT/api/v1/namespaces/$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace)/pods
{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {},
  "status": "Failure",
  "message": "pods is forbidden: User \"system:serviceaccount:dev:s1\" cannot list resource \"pods\" in API group \"\" in the namespace \"dev\"",
  "reason": "Forbidden",
  "details": {
    "kind": "pods"
  },
  "code": 403  #表示沒有許可權,無法進行訪問
}


#出現上面的原因就是沒有給s1這個服務賬戶繫結一些許可權,所以就顯示這樣的資訊
能夠訪問api  server,但是還是需要透過RBAC為service account授權,來決定這個使用者有許可權訪問api server中的哪些資源(deploy,pod,configmap等資源)


#對於這個service account進行授權的操作
##許可權和許可權繫結
[root@master serviceaccount]# kubectl apply -f s1-role.yaml 
role.rbac.authorization.k8s.io/s1-role created
rolebinding.rbac.authorization.k8s.io/s1-rolebinding created
[root@master serviceaccount]# cat s1-role.yaml 
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
   name: s1-role
   namespace: dev
rules:
- apiGroups: ["*"]
  resources: ["pods"]
  verbs: ["*"]

---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding 
metadata:
   name: s1-rolebinding
   namespace: dev
subjects:
- name: s1
  kind: ServiceAccount
  namespace: dev
  apiGroup: ""   #這個值就是對於service account的值
roleRef:
  kind: Role 
  name: s1-role
  apiGroup: rbac.authorization.k8s.io

#進入pod容器裡面進行訪問
[root@master serviceaccount]# kubectl exec -ti -n dev s1-pod -- /bin/bash
[root@s1-pod /]# curl --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt --header "Authorization:Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_SERVICE_PORT/api/v1/namespaces/$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace)/pods

{
  "kind": "PodList",
  "apiVersion": "v1",
  "metadata": {
    "resourceVersion": "25226"
  },
  "items": [
    {
      "metadata": {
        "name": "centos",
        "namespace": "dev",
        "uid": "c535288f-5894-45db-bcca-340936c895fd",
        "resourceVersion": "5503",
        "creationTimestamp": "2024-05-26T03:12:03Z",
        "managedFields": [

#省略資訊



  1. 上面命令引數的詳細介紹
#引數詳細的介紹
`--cacert`  用於指定一個ca證書檔案,用於驗證伺服器ssl證書
`--header`  引數用於新增http請求頭,Authorization:Bearer$這個是bearer令牌

https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_SERVICE_PORT/api/v1/namespaces/$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace)/pods

#這個是請求的url,指向k8s中api伺服器
$KUBERNETES_SERVICE_HOST 和 $KUBERNETES_SERVICE_PORT 是環境變數,分別代表 Kubernetes API 伺服器的主機名和埠號

/api/v1/namespaces/$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace)/pods 是 API 路徑,指定了要查詢的資源:

#讀取這個名稱空間下面的所有pod

3、賬戶相關的操作

#檢視上下文
[root@master ~]#  kubectl config get-contexts
CURRENT   NAME                          CLUSTER      AUTHINFO           NAMESPACE
          devuser@kubernetes            kubernetes   devuser            dev
*         kubernetes-admin@kubernetes   kubernetes   kubernetes-admin   

#檢視使用者相關的許可權,檢視繫結的相關
[root@master ~]# kubectl get rolebindings --all-namespaces | grep devuser
[root@master ~]# kubectl get clusterrolebindings | grep devuser


img

4、引數的配置

1、kind為role,clusterrole資源

1、verbs引數

#Role,ClusterRole Verbs可以配置引數,定義的是操作
* 包含所有的

get --- 讀取單個資源的詳細資訊,kubectl get pod my-pod -o yaml

list --- 列出這個名稱空間下面的所有資源,kubectl get pods


watch --- 用於監視資源的變化事件(新增,刪除,更新),kubectl get pods --watch

create --- 建立新的資源例項,kubectl create -f pod.yaml

update --- 用於更新現有的配置資訊,kubectl apply -f pod.yaml

patch --- 更新部分現有的資料,kubectl patch pod my-pod -p '{"spec":{"containers":[{"name":"my-container","image":"my-new-image"}]}}'

delete --- 刪除資料,kubectl delete pod my-pod

exec --- 在容器內執行命令,kubectl exec -it my-pod -- /bin/bash


2、resource引數

* 包含所有的資源型別

“services”, “endpoints”, “pods”,“secrets”,“configmaps”,“crontabs”,“deployments”,“jobs”,“nodes”,“rolebindings”,“clusterroles”,“daemonsets”,“replicasets”,“statefulsets”,“horizontalpodautoscalers”,“replicationcontrollers”,“cronjobs”

3、apigroup引數

#定義的是api資源,不同的型別
"*" --- 核心api組,pods,service,endpoint,namespace,nodes等
"apps" --- 控制器資源,deployments,daemonsets,statefulsets,replicasets等
"autoscaling" ---  API 組包含用於自動調整工作負載規模的資源,horizontalpodautoscalers (HPA)
"batch" --- API 組包含用於批處理任務的資源,jobs: 一次性任務,確保一個或多個 Pods 成功完成。
cronjobs: 基於時間排程的作業。

2、RoleBinding和ClusterRoleBinding引數

1、subject引數

subjects:
- kind: ServiceAccount   #認證賬戶,服務賬戶,還有別的引數User
  name: mark   #名字
  namespace: default   #會在這個名稱空間下面查詢這個使用者的
  apiGroup: ""  #這個*為service account的值,

2、roleRef引數

roleRef:   #繫結角色的方式
  kind: ClusterRole   #叢集角色繫結
  name: pod-clusterrole  #角色的名字
  apiGroup: rbac.authorization.k8s.io  #api 資源型別

5、理解

1、角色,叢集角色,角色繫結,叢集角色繫結

角色和叢集角色的作用範圍不同,一個是針對的名稱空間一個是針對叢集的
角色繫結只能繫結角色,有一個範圍,名稱空間
叢集角色繫結只能繫結叢集角色

2、關於主體

  1. Service account

    • service account就是有一個關聯的secret,掛載到了pod裡面的容器裡面了,訪問api server獲取(操作),靠的就是這些secret

    • 建立pod的時候指定service account,這樣secret就能掛載上去了

    • 角色繫結service account,這樣這個賬戶就能獲取許可權了,隨之裡面的pod也能獲取相應的許可權

    • 每一個pod裡面都有一個相關聯的service account

  2. User

    • 建立使用者比較的麻煩,建立使用者之後,繫結了角色,就能獲取在這個名稱空間下面操作許可權了
  3. Group

    • 同上

3、請求

  1. 理解的點
    • 在k8s中任何的請求與api server進行互動的時候,需要進行驗證身份

    • 然後進行授權(許可權鑑別),是否有操作

    • 更加精確的訪問控制

    • 記住是任何的請求

4、認證和授權流程

  1. 當有一個建立pod的請求傳送過來時

    • 先判斷他的身份是什麼,使用者還是,服務賬戶,認證成功後,與api server建立連線

    • 透過了認證的階段,然後進行RBAC許可權的鑑定,判斷這個使用者或者服務賬戶繫結的角色或者叢集角色是否有建立Pod的許可權,有則執行,沒有則拒絕(reject)

    • 這就是認證和授權的流程,

  2. 關於服務賬戶的話

    • 服務賬戶就是為了pod而活的

    • 進入pod裡面,向api server傳送請求(比如列出這個名稱空間下面的所有pod),判斷這個pod的service account的角色繫結是否有這個許可權,有則透過,

    • 這個目的主要就是管理pod而用的

    • 最重要的就是每個pod都必須有一個相關聯的service account賬戶

5、疑問

  1. 關於叢集角色
    • 叢集角色中的名稱空間和繫結有沒有影響,對於這個叢集角色?

    • 就是叢集角色是整個叢集內,跟名稱空間沒有關係,但是可以透過叢集角色繫結來繫結到一個名稱空間內,這樣的話就只能在這個名稱空間下面使用該許可權了

    • 叢集角色中有這個namespace的引數,但是這個不影響它,主要就是靠叢集角色繫結到名稱空間下來進行影響的

    • 如果不設定名稱空間的話,那麼在所有名稱空間內都有這個許可權

相關文章