kubernetes 之訪問安全控制 - RBAC

October 23, 2021

RBAC(Role-Based Access Control),它將權限授予角色(role)上,可以想像它是一個責任。對 RBAC 來說,使用者(User)是一個獨立可存取資源的主體(Subject)。這過程中被允許對一或多個 Object 執行的操作可以稱做許可(Permission),一個使用者可藉由授權而擁有多個 role。

  人
  O
 \|/
 / \         action(verb)
Subject --------------------> Object

RBAC 中 User、Role 和 Permission 關係如下

                            ___________________________
       -----> Role         |       Permissions         |
     /             \       |                           |
User                -----> | Operations -----> Objects |
     \             /       |                           |
       -----> Role         |___________________________|

RBAC 是一個限定操作的機制,用於定義誰(subject)能或不能操作(verb)哪個物件(object)。動作的發出者(subject)可以是一個 User Accoun 或是 Service Account;verb 表示要執行的操作 create、apply、delete、update、patch、edit 和 get 等;object 是指要被操作的目標資源,以 Kubernetes API 來看是以 URL 作為對象。

RBAC 支援 RoleClusterRole 兩種角色,前者是 namespace 級別後者則是集群級別,對這兩類給權限時,需要用到 RoleBindingClusterRoleBinding。RoleBinding 將 role 上的 Permissions 綁定到一個或一組使用者上,此綁定只能隸屬於某一個 namespaceClusterRoleBinding 則用於及群集別。

在一個 namespace 下可以包含多個 RoleRoleBinding 對象,集群級別也是可存在多個 ClusterRoleClusterRoleBinding。一個使用者可以經由 RoleBindingClusterRoleBinding 關連至多個角色,並實現多重授權。

Role 和 RoleBinding

Role 僅是一組 permission 權限的集合,在 Role 類型的 yaml 檔中使用 rules 字段定義授權規則。下面是一個 Kubernetes Dashboard 的 Role 範例,它監視了 secretsconfigmapsservices 資源的權限。

kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kubernetes-dashboard
rules:
  # Allow Dashboard to get, update and delete Dashboard exclusive secrets.
  - apiGroups: [""]
    resources: ["secrets"]
    resourceNames: ["kubernetes-dashboard-key-holder", "kubernetes-dashboard-certs", "kubernetes-dashboard-csrf"]
    verbs: ["get", "update", "delete"]
    # Allow Dashboard to get and update 'kubernetes-dashboard-settings' config map.
  - apiGroups: [""]
    resources: ["configmaps"]
    resourceNames: ["kubernetes-dashboard-settings"]
    verbs: ["get", "update"]
    # Allow Dashboard to get metrics.
  - apiGroups: [""]
    resources: ["services"]
    resourceNames: ["heapster", "dashboard-metrics-scraper"]
    verbs: ["proxy"]
  - apiGroups: [""]
    resources: ["services/proxy"]
    resourceNames: ["heapster", "http:heapster:", "https:heapster:", "dashboard-metrics-scraper", "http:dashboard-metrics-scraper"]
    verbs: ["get"]

rules 下定義了規則其字段有。

  1. apiGroups 包含 API 組的名稱,可以使用列表方式定義,如果以 "" 表示是 core API group。
  2. resource 要將規範應用的目標資源種類(pods、deployments…),同樣可以列表方式呈現。ResourceAll 表示所有資源
  3. resourceNames 要將規範應用的目標資源種類下名稱,如果為空表示所有資源
  4. verbs 資源類型的操作,有 get、list、create、update、patch、watch、proxy、redirect、delete 和 deletecollection
  5. nonResourceURLs 定義用戶應該有權限訪問的網址列表,非 namespace 級別,因此適用於 ClusterRole 和 ClusterRoleBinding

在範例中 resources: ["services/proxy"] 表示 proxy 是 services 的子資源,因此使用 resource/subre-source 格式呈現。

以下是一個透過 kubectl create role 建立 role 資源的快速方式

kubectl create role pods-reader --verb="get,list,watch" --resource="pods,pods/log" -n test
kubectl create role service-admin --verb="*" --resource="service,services/*" -n test
role.rbac.authorization.k8s.io/service-admin created

kubectl -n test describe role service-admin
Name:         service-admin
Labels:       <none>
Annotations:  <none>
PolicyRule:
  Resources   Non-Resource URLs  Resource Names  Verbs
  ---------   -----------------  --------------  -----
  services/*  []                 []              [*]
  services    []                 []              [*]

建立 role 後需要綁定 Role-Binding 到 subject 上才有作用。RoleBinding 用於將 Role 中定義的權限賦予一個或一組用戶,它由一組 subject 以及一個要引用來賦予這組 subjectRoleClusterRole 組成。

kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: reader-resource
  namespace: test
subjects: # 要綁定的 subject
  - kind: User
    name: kube-user1
    apiGroup: rbac.authorization.k8s.io
roleRef: # 要綁定的 Role 或 ClusterRole 資源
  kind: Role
  name: pods-reader
  apiGroup: rbac.authorization.k8s.io

透過指令方式

kubectl create rolebinding reader-resource --role=pods-reader --user=kube-user1 -n testing

Role 和 RoleBinding 屬於 namespace 級別,有時須注意非 namespace 級別的資源,如 PersistentVolumeNameSpaceNode 等,而這些資源就得用 ClusterRoleClusterRoleBinding 進行配置。

ClusterRole 和 ClusterRoleBinding

ClusterRole 能夠管理和 Role 資源一樣的准許權限外,還可以管理集群資源的授權。下面為一個 kubernetes dashboard 範例,由於不屬於 namespace 級別,因此不會有其字段。

---

kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
rules:
  # Allow Metrics Scraper to get metrics from the Metrics server
  - apiGroups: ["metrics.k8s.io"]
    resources: ["pods", "nodes"]
    verbs: ["get", "list", "watch"]

---

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kubernetes-dashboard
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: kubernetes-dashboard
subjects:
  - kind: ServiceAccount
    name: kubernetes-dashboard
    namespace: kubernetes-dashboard

---

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: kubernetes-dashboard
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: kubernetes-dashboard
subjects:
  - kind: ServiceAccount
    name: kubernetes-dashboard
    namespace: kubernetes-dashboard

---

RoleBinding 也能將 subject 綁定 ClusterRole 資源,但權限會被 RoleBinding 所限制,也就是 ClusterRole 所賦予權限只能使用在 RoleBinding 所在的 namespace。系統預設下建立許多的 ClusterRole 資源

○ → kubectl get clusterrole 
NAME                                                                   CREATED AT
admin                                                                  2021-11-27T08:03:26Z
cilium                                                                 2021-11-27T08:03:31Z
cilium-operator                                                        2021-11-27T08:03:31Z
cluster-admin                                                          2021-11-27T08:03:26Z
edit                                                                   2021-11-27T08:03:26Z
kubeadm:get-nodes                                                      2021-11-27T08:03:28Z
...

創建使用者與綁定角色範例

openssl genrsa -out itachi.key 2048
openssl req -new -key itachi.key -out itachi.csr -subj "/CN=itachi/O=test"
sudo openssl x509 -req -in itachi.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key  -CAcreateserial -out itachi.crt -days 30
kubectl config set-credentials itachi --client-certificate itachi.crt --client-key itachi.key
kubectl config set-context itachi-context --cluster=kubernetes --namespace=test --user=itachi
kubectl --context=itachi-context get pod
Error from server (Forbidden): pods is forbidden: User "itachi" cannot list resource "pods" in API group "" in the namespace "test"

發生無權限存取。此時將 Role 範例的 User 設定成 itachi 即可

kubectl --context=itachi-context get pods
No resources found in test namespace.

刪除使用者

kubectl config unset users.itachi