使用 RBAC 授權

基於角色的存取控制 (RBAC) 是一種根據組織內個別使用者的角色來規範對電腦或網路資源存取的方法。

RBAC 授權使用 rbac.authorization.k8s.io API 群組 來驅動授權決策,讓您透過 Kubernetes API 動態設定策略。

若要啟用 RBAC,請啟動 API 伺服器,並將 --authorization-config 旗標設定為包含 RBAC 授權器的檔案;例如

apiVersion: apiserver.config.k8s.io/v1
kind: AuthorizationConfiguration
authorizers:
  ...
  - type: RBAC
  ...

或者,啟動 API 伺服器,並將 --authorization-mode 旗標設定為包含 RBAC 的逗號分隔清單;例如

kube-apiserver --authorization-mode=...,RBAC --other-options --more-options

API 物件

RBAC API 宣告四種類型的 Kubernetes 物件:RoleClusterRoleRoleBindingClusterRoleBinding。您可以像其他任何 Kubernetes 物件一樣,使用 kubectl 等工具來描述或修改 RBAC 物件

Role 與 ClusterRole

RBAC RoleClusterRole 包含代表一組權限的規則。權限是純粹累加的(沒有「拒絕」規則)。

Role 始終在特定的命名空間內設定權限;當您建立 Role 時,必須指定它所屬的命名空間。

ClusterRole 相反,是一種非命名空間資源。資源具有不同的名稱(Role 和 ClusterRole),因為 Kubernetes 物件始終必須是命名空間或非命名空間;它不能兩者兼具。

ClusterRole 有幾種用途。您可以使用 ClusterRole 來

  1. 定義命名空間資源的權限,並在個別命名空間中授予存取權
  2. 定義命名空間資源的權限,並在所有命名空間中授予存取權
  3. 定義叢集範圍資源的權限

如果您想在命名空間內定義角色,請使用 Role;如果您想定義叢集範圍的角色,請使用 ClusterRole。

Role 範例

以下是「預設」命名空間中的 Role 範例,可用於授予對 pod 的讀取權限

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: pod-reader
rules:
- apiGroups: [""] # "" indicates the core API group
  resources: ["pods"]
  verbs: ["get", "watch", "list"]

ClusterRole 範例

ClusterRole 可用於授予與 Role 相同的權限。由於 ClusterRole 是叢集範圍的,因此您也可以使用它們來授予對以下項目的存取權

  • 叢集範圍資源(例如 節點

  • 非資源端點(例如 /healthz

  • 跨所有命名空間的命名空間資源(例如 Pod)

    例如:您可以使用 ClusterRole 允許特定使用者執行 kubectl get pods --all-namespaces

以下是 ClusterRole 的範例,可用於授予對任何特定命名空間或跨所有命名空間中的 secret 的讀取權限(取決於它的繫結方式)

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  # "namespace" omitted since ClusterRoles are not namespaced
  name: secret-reader
rules:
- apiGroups: [""]
  #
  # at the HTTP level, the name of the resource for accessing Secret
  # objects is "secrets"
  resources: ["secrets"]
  verbs: ["get", "watch", "list"]

Role 或 ClusterRole 物件的名稱必須是有效的路徑區段名稱

RoleBinding 與 ClusterRoleBinding

角色繫結會將角色中定義的權限授予使用者或一組使用者。它包含 subjects(使用者、群組或服務帳戶)的清單,以及對正在授予的角色的參考。RoleBinding 在特定命名空間內授予權限,而 ClusterRoleBinding 則在叢集範圍內授予該存取權。

RoleBinding 可能會參照相同命名空間中的任何 Role。或者,RoleBinding 可以參照 ClusterRole,並將該 ClusterRole 繫結至 RoleBinding 的命名空間。如果您想要將 ClusterRole 繫結至叢集中的所有命名空間,您可以使用 ClusterRoleBinding。

RoleBinding 或 ClusterRoleBinding 物件的名稱必須是有效的路徑區段名稱

RoleBinding 範例

以下是一個 RoleBinding 的範例,它將 "pod-reader" Role 授與給 "default" 命名空間中的使用者 "jane"。這允許 "jane" 讀取 "default" 命名空間中的 Pod。

apiVersion: rbac.authorization.k8s.io/v1
# This role binding allows "jane" to read pods in the "default" namespace.
# You need to already have a Role named "pod-reader" in that namespace.
kind: RoleBinding
metadata:
  name: read-pods
  namespace: default
subjects:
# You can specify more than one "subject"
- kind: User
  name: jane # "name" is case sensitive
  apiGroup: rbac.authorization.k8s.io
roleRef:
  # "roleRef" specifies the binding to a Role / ClusterRole
  kind: Role #this must be Role or ClusterRole
  name: pod-reader # this must match the name of the Role or ClusterRole you wish to bind to
  apiGroup: rbac.authorization.k8s.io

RoleBinding 也可以參照 ClusterRole,以將該 ClusterRole 中定義的權限授與給 RoleBinding 命名空間內的資源。這種參照方式讓您可以在叢集中定義一組通用的角色,然後在多個命名空間中重複使用它們。

例如,即使以下 RoleBinding 參照了 ClusterRole,"dave" (主體,區分大小寫) 也只能讀取 "development" 命名空間中的 Secrets,因為 RoleBinding 的命名空間 (在其 metadata 中) 是 "development"。

apiVersion: rbac.authorization.k8s.io/v1
# This role binding allows "dave" to read secrets in the "development" namespace.
# You need to already have a ClusterRole named "secret-reader".
kind: RoleBinding
metadata:
  name: read-secrets
  #
  # The namespace of the RoleBinding determines where the permissions are granted.
  # This only grants permissions within the "development" namespace.
  namespace: development
subjects:
- kind: User
  name: dave # Name is case sensitive
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: secret-reader
  apiGroup: rbac.authorization.k8s.io

ClusterRoleBinding 範例

若要跨整個叢集授與權限,您可以使用 ClusterRoleBinding。以下 ClusterRoleBinding 允許 "manager" 群組中的任何使用者讀取任何命名空間中的 Secrets。

apiVersion: rbac.authorization.k8s.io/v1
# This cluster role binding allows anyone in the "manager" group to read secrets in any namespace.
kind: ClusterRoleBinding
metadata:
  name: read-secrets-global
subjects:
- kind: Group
  name: manager # Name is case sensitive
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: secret-reader
  apiGroup: rbac.authorization.k8s.io

建立繫結後,您就無法變更其參照的 Role 或 ClusterRole。如果您嘗試變更繫結的 roleRef,您會收到驗證錯誤。如果您確實想要變更繫結的 roleRef,您需要移除該繫結物件並建立一個替代物件。

此限制有兩個原因

  1. 使 roleRef 不可變更,允許授與某人現有繫結物件的 update 權限,以便他們可以管理主體清單,而無需變更授與給這些主體的角色。
  2. 繫結至不同的角色在本質上是不同的繫結。要求為了變更 roleRef 而刪除/重新建立繫結,可確保繫結中的完整主體清單旨在被授與新的角色 (而不是僅啟用或意外修改 roleRef 而未驗證是否應將新角色的權限授與給所有現有的主體)。

kubectl auth reconcile 命令列工具會建立或更新包含 RBAC 物件的清單檔案,並在需要變更其參照的角色時處理刪除和重新建立繫結物件。請參閱命令用法和範例以取得更多資訊。

參照資源

在 Kubernetes API 中,大多數資源都使用其物件名稱的字串表示形式來表示和存取,例如 Pod 的 pods。RBAC 使用與相關 API 端點 URL 中顯示的完全相同的名稱來參照資源。某些 Kubernetes API 涉及子資源,例如 Pod 的日誌。對 Pod 日誌的請求看起來像這樣

GET /api/v1/namespaces/{namespace}/pods/{name}/log

在這種情況下,pods 是 Pod 資源的命名空間資源,而 logpods 的子資源。若要在 RBAC 角色中表示這一點,請使用斜線 (/) 來分隔資源和子資源。若要允許主體讀取 pods 並存取每個 Pod 的 log 子資源,您可以撰寫

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: pod-and-pod-logs-reader
rules:
- apiGroups: [""]
  resources: ["pods", "pods/log"]
  verbs: ["get", "list"]

您也可以透過 resourceNames 清單,依名稱參照特定請求的資源。指定後,請求可以限制為資源的個別實例。以下範例限制其主體只能 getupdate 名為 my-configmapConfigMap

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: configmap-updater
rules:
- apiGroups: [""]
  #
  # at the HTTP level, the name of the resource for accessing ConfigMap
  # objects is "configmaps"
  resources: ["configmaps"]
  resourceNames: ["my-configmap"]
  verbs: ["update", "get"]

您可以不用參照個別的 resourcesapiGroupsverbs,而是使用萬用字元 * 符號來參照所有此類物件。對於 nonResourceURLs,您可以使用萬用字元 * 作為後綴全域比對。對於 resourceNames,空集合表示允許所有項目。以下範例允許對 example.com API 群組中所有目前和未來的資源執行任何目前和未來的動作。這與內建的 cluster-admin 角色類似。

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: example.com-superuser # DO NOT USE THIS ROLE, IT IS JUST AN EXAMPLE
rules:
- apiGroups: ["example.com"]
  resources: ["*"]
  verbs: ["*"]

彙總的 ClusterRole

您可以將多個 ClusterRole 彙總為一個組合的 ClusterRole。作為叢集控制平面一部分執行的控制器,會監看設定了 aggregationRule 的 ClusterRole 物件。aggregationRule 定義了一個標籤選取器,控制器使用它來比對其他應組合到此物件 rules 欄位中的 ClusterRole 物件。

以下是彙總的 ClusterRole 範例

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: monitoring
aggregationRule:
  clusterRoleSelectors:
  - matchLabels:
      rbac.example.com/aggregate-to-monitoring: "true"
rules: [] # The control plane automatically fills in the rules

如果您建立一個新的 ClusterRole,它符合現有彙總 ClusterRole 的標籤選取器,則該變更會觸發將新規則新增到彙總 ClusterRole 中。以下範例透過建立另一個標籤為 rbac.example.com/aggregate-to-monitoring: true 的 ClusterRole,將規則新增到 "monitoring" ClusterRole。

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: monitoring-endpoints
  labels:
    rbac.example.com/aggregate-to-monitoring: "true"
# When you create the "monitoring-endpoints" ClusterRole,
# the rules below will be added to the "monitoring" ClusterRole.
rules:
- apiGroups: [""]
  resources: ["services", "endpointslices", "pods"]
  verbs: ["get", "list", "watch"]

預設的使用者導向角色使用 ClusterRole 彙總。這讓您作為叢集管理員,可以包含自訂資源的規則,例如由 CustomResourceDefinitions 或彙總的 API 伺服器提供的資源,以擴充預設角色。

例如:以下 ClusterRole 允許 "admin" 和 "edit" 預設角色管理名為 CronTab 的自訂資源,而 "view" 角色只能對 CronTab 資源執行讀取動作。您可以假設 CronTab 物件在 API 伺服器看到的 URL 中名為 "crontabs"

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: aggregate-cron-tabs-edit
  labels:
    # Add these permissions to the "admin" and "edit" default roles.
    rbac.authorization.k8s.io/aggregate-to-admin: "true"
    rbac.authorization.k8s.io/aggregate-to-edit: "true"
rules:
- apiGroups: ["stable.example.com"]
  resources: ["crontabs"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: aggregate-cron-tabs-view
  labels:
    # Add these permissions to the "view" default role.
    rbac.authorization.k8s.io/aggregate-to-view: "true"
rules:
- apiGroups: ["stable.example.com"]
  resources: ["crontabs"]
  verbs: ["get", "list", "watch"]

角色範例

以下範例是 Role 或 ClusterRole 物件的摘錄,僅顯示 rules 區段。

允許讀取核心 API 群組中的 "pods" 資源

rules:
- apiGroups: [""]
  #
  # at the HTTP level, the name of the resource for accessing Pod
  # objects is "pods"
  resources: ["pods"]
  verbs: ["get", "list", "watch"]

允許在 "apps" API 群組中讀取/寫入 Deployments (在 HTTP 層級:URL 的資源部分中具有 "deployments" 的物件)

rules:
- apiGroups: ["apps"]
  #
  # at the HTTP level, the name of the resource for accessing Deployment
  # objects is "deployments"
  resources: ["deployments"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]

允許讀取核心 API 群組中的 Pod,以及讀取或寫入 "batch" API 群組中的 Job 資源

rules:
- apiGroups: [""]
  #
  # at the HTTP level, the name of the resource for accessing Pod
  # objects is "pods"
  resources: ["pods"]
  verbs: ["get", "list", "watch"]
- apiGroups: ["batch"]
  #
  # at the HTTP level, the name of the resource for accessing Job
  # objects is "jobs"
  resources: ["jobs"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]

允許讀取名為 "my-config" 的 ConfigMap (必須與 RoleBinding 繫結,以限制為單一命名空間中的單一 ConfigMap)

rules:
- apiGroups: [""]
  #
  # at the HTTP level, the name of the resource for accessing ConfigMap
  # objects is "configmaps"
  resources: ["configmaps"]
  resourceNames: ["my-config"]
  verbs: ["get"]

允許讀取核心群組中的資源 "nodes" (由於 Node 是叢集範圍的,因此必須在與 ClusterRoleBinding 繫結的 ClusterRole 中才能生效)

rules:
- apiGroups: [""]
  #
  # at the HTTP level, the name of the resource for accessing Node
  # objects is "nodes"
  resources: ["nodes"]
  verbs: ["get", "list", "watch"]

允許對非資源端點 /healthz 和所有子路徑發出 GET 和 POST 請求 (必須在與 ClusterRoleBinding 繫結的 ClusterRole 中才能生效)

rules:
- nonResourceURLs: ["/healthz", "/healthz/*"] # '*' in a nonResourceURL is a suffix glob match
  verbs: ["get", "post"]

參照主體

RoleBinding 或 ClusterRoleBinding 將角色繫結至主體。主體可以是群組、使用者或 ServiceAccount

Kubernetes 將使用者名稱表示為字串。這些可以是:純名稱,例如 "alice";電子郵件樣式名稱,如 "bob@example.com";或表示為字串的數字使用者 ID。作為叢集管理員,您有責任組態身分驗證模組,以便身分驗證產生您想要的格式的使用者名稱。

在 Kubernetes 中,Authenticator 模組提供群組資訊。群組與使用者一樣,表示為字串,並且該字串沒有格式要求,除了前綴 system: 是保留的。

ServiceAccount 的名稱以 system:serviceaccount: 為前綴,並屬於名稱以 system:serviceaccounts: 為前綴的群組。

RoleBinding 範例

以下範例是 RoleBinding 摘錄,僅顯示 subjects 區段。

對於名為 alice@example.com 的使用者

subjects:
- kind: User
  name: "alice@example.com"
  apiGroup: rbac.authorization.k8s.io

對於名為 frontend-admins 的群組

subjects:
- kind: Group
  name: "frontend-admins"
  apiGroup: rbac.authorization.k8s.io

對於 "kube-system" 命名空間中的預設服務帳戶

subjects:
- kind: ServiceAccount
  name: default
  namespace: kube-system

對於 "qa" 命名空間中的所有服務帳戶

subjects:
- kind: Group
  name: system:serviceaccounts:qa
  apiGroup: rbac.authorization.k8s.io

對於任何命名空間中的所有服務帳戶

subjects:
- kind: Group
  name: system:serviceaccounts
  apiGroup: rbac.authorization.k8s.io

對於所有已驗證的使用者

subjects:
- kind: Group
  name: system:authenticated
  apiGroup: rbac.authorization.k8s.io

對於所有未經驗證的使用者

subjects:
- kind: Group
  name: system:unauthenticated
  apiGroup: rbac.authorization.k8s.io

對於所有使用者

subjects:
- kind: Group
  name: system:authenticated
  apiGroup: rbac.authorization.k8s.io
- kind: Group
  name: system:unauthenticated
  apiGroup: rbac.authorization.k8s.io

預設角色和角色繫結

API 伺服器會建立一組預設的 ClusterRole 和 ClusterRoleBinding 物件。其中許多都帶有 system: 前綴,表示該資源由叢集控制平面直接管理。所有預設的 ClusterRole 和 ClusterRoleBinding 都標有 kubernetes.io/bootstrapping=rbac-defaults 標籤。

自動協調

在每次啟動時,API 伺服器都會使用任何遺失的權限來更新預設叢集角色,並使用任何遺失的主體來更新預設叢集角色繫結。這允許叢集修復意外的修改,並有助於在新的 Kubernetes 版本中權限和主體變更時,保持角色和角色繫結為最新狀態。

若要選擇退出此協調,請將預設叢集角色或預設叢集 RoleBinding 上的 rbac.authorization.kubernetes.io/autoupdate 註解設定為 false。請注意,遺失預設權限和主體可能會導致叢集無法運作。

如果 RBAC 授權器處於活動狀態,則預設會啟用自動協調。

API 探索角色

預設叢集角色繫結授權未經驗證和已驗證的使用者讀取被視為可公開存取的 API 資訊 (包括 CustomResourceDefinitions)。若要停用匿名未經驗證的存取,請將 --anonymous-auth=false 標誌新增至 API 伺服器組態。

若要透過 kubectl 檢視這些角色的組態,請執行

kubectl get clusterroles system:discovery -o yaml
Kubernetes RBAC API 探索角色
預設 ClusterRole預設 ClusterRoleBinding描述
system:basic-usersystem:authenticated 群組允許使用者對自己的基本資訊進行唯讀存取。在 v1.14 之前,此角色也預設繫結至system:unauthenticated
system:discoverysystem:authenticated 群組允許對 API 探索端點進行唯讀存取,這些端點是探索和協商 API 層級所需的。在 v1.14 之前,此角色也繫結至system:unauthenticated
system:public-info-viewersystem:authenticatedsystem:unauthenticated 群組允許對叢集的非敏感資訊進行唯讀存取。在 Kubernetes v1.14 中導入。

使用者導向角色

某些預設 ClusterRole 沒有 system: 前綴。這些是旨在成為使用者導向的角色。它們包括超級使用者角色 (cluster-admin)、旨在透過 ClusterRoleBinding 在叢集範圍內授與的角色,以及旨在透過 RoleBinding 在特定命名空間內授與的角色 (admineditview)。

使用者導向的 ClusterRole 使用ClusterRole 彙總,以允許管理員在這些 ClusterRole 上包含自訂資源的規則。若要將規則新增至 admineditview 角色,請建立具有以下一個或多個標籤的 ClusterRole

metadata:
  labels:
    rbac.authorization.k8s.io/aggregate-to-admin: "true"
    rbac.authorization.k8s.io/aggregate-to-edit: "true"
    rbac.authorization.k8s.io/aggregate-to-view: "true"

預設 ClusterRole預設 ClusterRoleBinding描述
cluster-adminsystem:masters 群組允許超級使用者存取權限,以對任何資源執行任何動作。在 ClusterRoleBinding 中使用時,它會授予對叢集中和所有命名空間中每個資源的完全控制權。在 RoleBinding 中使用時,它會授予對角色繫結命名空間中每個資源 (包括命名空間本身) 的完全控制權。
admin允許管理員存取權限,旨在透過 RoleBinding 在命名空間內授與。

如果在 RoleBinding 中使用,則允許對命名空間中大多數資源進行讀寫存取,包括在命名空間內建立角色和角色繫結的能力。此角色不允許寫入資源配額或命名空間本身。此角色也不允許寫入 Kubernetes v1.22+ 建立的叢集中的 EndpointSlices (或 Endpoints)。更多資訊請參閱「EndpointSlices 和 Endpoints 的寫入存取權限」區段

edit允許對命名空間中的大多數物件進行讀寫存取。

此角色不允許檢視或修改角色或角色繫結。但是,此角色允許以命名空間中任何 ServiceAccount 的身分存取 Secrets 和執行 Pod,因此可用於取得命名空間中任何 ServiceAccount 的 API 存取層級。此角色也不允許寫入 Kubernetes v1.22+ 建立的叢集中的 EndpointSlices (或 Endpoints)。更多資訊請參閱「EndpointSlices 和 Endpoints 的寫入存取權限」區段

view允許唯讀存取權限,以檢視命名空間中的大多數物件。它不允許檢視角色或角色繫結。

此角色不允許檢視 Secrets,因為讀取 Secrets 的內容會啟用對命名空間中 ServiceAccount 憑證的存取,這將允許以命名空間中任何 ServiceAccount 的身分進行 API 存取 (一種權限提升形式)。

核心組件角色

預設 ClusterRole預設 ClusterRoleBinding描述
system:kube-schedulersystem:kube-scheduler 使用者允許存取 排程器組件所需的資源。
system:volume-schedulersystem:kube-scheduler 使用者允許存取 kube-scheduler 組件所需的磁碟區資源。
system:kube-controller-managersystem:kube-controller-manager 使用者允許存取 控制器管理器組件所需的資源。個別控制器所需的權限在控制器角色中詳細說明。
system:node允許存取 kubelet 所需的資源,包括對所有 Secrets 的讀取存取權限,以及對所有 pod 狀態物件的寫入存取權限

您應該使用Node 授權器NodeRestriction 許可控制器外掛程式,而不是system:node角色,並允許根據排程在其上執行的 Pod,授與 kubelet API 存取權限。

system:node角色僅為了與從 v1.8 之前的版本升級的 Kubernetes 叢集相容而存在。

system:node-proxiersystem:kube-proxy 使用者允許存取 kube-proxy 組件所需的資源。

其他組件角色

預設 ClusterRole預設 ClusterRoleBinding描述
system:auth-delegator允許委派的身分驗證和授權檢查。這通常由附加元件 API 伺服器用於統一的身分驗證和授權。
system:heapster用於 Heapster 組件的角色 (已棄用)。
system:kube-aggregator用於 kube-aggregator 組件的角色。
system:kube-dnskube-dns 服務帳戶在 kube-system 命名空間中用於 kube-dns 組件的角色。
system:kubelet-api-admin允許完全存取 kubelet API。
system:node-bootstrapper允許存取執行 kubelet TLS 啟動引導所需的資源。
system:node-problem-detector用於 node-problem-detector 組件的角色。
system:persistent-volume-provisioner允許存取大多數動態磁碟區佈建器所需的資源。
system:monitoringsystem:monitoring 群組允許讀取存取控制平面監控端點 (即kube-apiserver 活性和就緒端點 (/healthz, /livez, /readyz)、個別的健康檢查端點 (/healthz/*, /livez/*, /readyz/*) 和/metrics)。請注意,個別的健康檢查端點和指標端點可能會公開敏感資訊。

內建控制器的角色

Kubernetes 控制器管理器執行控制器,這些控制器是內建於 Kubernetes 控制平面中的。當使用 --use-service-account-credentials 叫用時,kube-controller-manager 會使用個別的服務帳戶啟動每個控制器。每個內建控制器都存在對應的角色,前綴為 system:controller:。如果控制器管理器未使用 --use-service-account-credentials 啟動,它會使用自己的憑證執行所有控制迴圈,必須將所有相關角色授與給該憑證。這些角色包括

  • system:controller:attachdetach-controller
  • system:controller:certificate-controller
  • system:controller:clusterrole-aggregation-controller
  • system:controller:cronjob-controller
  • system:controller:daemon-set-controller
  • system:controller:deployment-controller
  • system:controller:disruption-controller
  • system:controller:endpoint-controller
  • system:controller:expand-controller
  • system:controller:generic-garbage-collector
  • system:controller:horizontal-pod-autoscaler
  • system:controller:job-controller
  • system:controller:namespace-controller
  • system:controller:node-controller
  • system:controller:persistent-volume-binder
  • system:controller:pod-garbage-collector
  • system:controller:pv-protection-controller
  • system:controller:pvc-protection-controller
  • system:controller:replicaset-controller
  • system:controller:replication-controller
  • system:controller:resourcequota-controller
  • system:controller:root-ca-cert-publisher
  • system:controller:route-controller
  • system:controller:service-account-controller
  • system:controller:service-controller
  • system:controller:statefulset-controller
  • system:controller:ttl-controller

權限提升預防和啟動引導

RBAC API 防止使用者透過編輯角色或角色繫結來提升權限。由於這是於 API 層級強制執行的,因此即使未使用 RBAC 授權器,它仍然適用。

角色建立或更新的限制

只有在以下至少一項為真的情況下,您才能建立/更新角色

  1. 您已經擁有角色中包含的所有權限,並且範圍與正在修改的物件相同 (對於 ClusterRole 為叢集範圍,對於 Role 為相同命名空間或叢集範圍)。
  2. 您被明確授予對 rbac.authorization.k8s.io API 群組中的 rolesclusterroles 資源執行 escalate 動詞的權限。

例如,如果 user-1 沒有叢集範圍內列出 Secrets 的能力,他們就無法建立包含該權限的 ClusterRole。若要允許使用者建立/更新角色

  1. 授與他們一個允許他們建立/更新 Role 或 ClusterRole 物件的角色 (依所需)。
  2. 授與他們在他們建立/更新的角色中包含特定權限的權限
    • 隱含地,透過給予他們這些權限 (如果他們嘗試建立或修改 Role 或 ClusterRole,但其中包含他們自己未被授與的權限,則 API 請求將被禁止)
    • 或明確地允許在 RoleClusterRole 中指定任何權限,方法是給予他們在 rbac.authorization.k8s.io API 群組中的 rolesclusterroles 資源上執行 escalate 動詞的權限

角色繫結建立或更新的限制

只有在您已經擁有參照角色中包含的所有權限 (範圍與角色繫結相同) 您已被授權對參照角色執行 bind 動詞的情況下,您才能建立/更新角色繫結。例如,如果 user-1 沒有叢集範圍內列出 Secrets 的能力,他們就無法建立 ClusterRoleBinding 以繫結至授與該權限的角色。若要允許使用者建立/更新角色繫結

  1. 授與他們一個允許他們建立/更新 RoleBinding 或 ClusterRoleBinding 物件的角色 (依所需)。
  2. 授與他們繫結特定角色所需的權限
    • 隱含地,透過給予他們角色中包含的權限。
    • 明確地,透過給予他們對特定 Role (或 ClusterRole) 執行 bind 動詞的權限。

例如,此 ClusterRole 和 RoleBinding 將允許 user-1 在命名空間 user-1-namespace 中授與其他使用者 admineditview 角色

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: role-grantor
rules:
- apiGroups: ["rbac.authorization.k8s.io"]
  resources: ["rolebindings"]
  verbs: ["create"]
- apiGroups: ["rbac.authorization.k8s.io"]
  resources: ["clusterroles"]
  verbs: ["bind"]
  # omit resourceNames to allow binding any ClusterRole
  resourceNames: ["admin","edit","view"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: role-grantor-binding
  namespace: user-1-namespace
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: role-grantor
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: user-1

在啟動引導第一個角色和角色繫結時,初始使用者必須授與他們尚未擁有的權限。若要啟動引導初始角色和角色繫結

  • 使用具有 "system:masters" 群組的憑證,該憑證預設繫結至 "cluster-admin" 超級使用者角色。

命令列工具

kubectl create role

建立 Role 物件,定義單一命名空間內的權限。範例

  • 建立名為 "pod-reader" 的 Role,允許使用者對 Pod 執行 getwatchlist

    kubectl create role pod-reader --verb=get --verb=list --verb=watch --resource=pods
    
  • 建立名為 "pod-reader" 的 Role,並指定 resourceNames

    kubectl create role pod-reader --verb=get --resource=pods --resource-name=readablepod --resource-name=anotherpod
    
  • 建立名為 "foo" 的 Role,並指定 apiGroups

    kubectl create role foo --verb=get,list,watch --resource=replicasets.apps
    
  • 建立名為 "foo" 的 Role,並指定子資源權限

    kubectl create role foo --verb=get,list,watch --resource=pods,pods/status
    
  • 建立名為 "my-component-lease-holder" 的 Role,並具有取得/更新具有特定名稱的資源的權限

    kubectl create role my-component-lease-holder --verb=get,list,watch,update --resource=lease --resource-name=my-component
    

kubectl create clusterrole

建立 ClusterRole。範例

  • 建立名為 "pod-reader" 的 ClusterRole,允許使用者對 Pod 執行 getwatchlist

    kubectl create clusterrole pod-reader --verb=get,list,watch --resource=pods
    
  • 建立名為 "pod-reader" 的 ClusterRole,並指定 resourceNames

    kubectl create clusterrole pod-reader --verb=get --resource=pods --resource-name=readablepod --resource-name=anotherpod
    
  • 建立名為 "foo" 的 ClusterRole,並指定 apiGroups

    kubectl create clusterrole foo --verb=get,list,watch --resource=replicasets.apps
    
  • 建立名為 "foo" 的 ClusterRole,並指定子資源權限

    kubectl create clusterrole foo --verb=get,list,watch --resource=pods,pods/status
    
  • 建立名為 "foo" 的 ClusterRole,並指定 nonResourceURL

    kubectl create clusterrole "foo" --verb=get --non-resource-url=/logs/*
    
  • 建立名為 "monitoring" 的 ClusterRole,並指定 aggregationRule

    kubectl create clusterrole monitoring --aggregation-rule="rbac.example.com/aggregate-to-monitoring=true"
    

kubectl create rolebinding

在特定命名空間內授與 Role 或 ClusterRole。範例

  • 在 "acme" 命名空間內,將 "admin" ClusterRole 中的權限授與給名為 "bob" 的使用者

    kubectl create rolebinding bob-admin-binding --clusterrole=admin --user=bob --namespace=acme
    
  • 在 "acme" 命名空間內,將 "view" ClusterRole 中的權限授與給 "acme" 命名空間中名為 "myapp" 的服務帳戶

    kubectl create rolebinding myapp-view-binding --clusterrole=view --serviceaccount=acme:myapp --namespace=acme
    
  • 在 "acme" 命名空間內,將 "view" ClusterRole 中的權限授與給 "myappnamespace" 命名空間中名為 "myapp" 的服務帳戶

    kubectl create rolebinding myappnamespace-myapp-view-binding --clusterrole=view --serviceaccount=myappnamespace:myapp --namespace=acme
    

kubectl create clusterrolebinding

跨整個叢集 (所有命名空間) 授與 ClusterRole。範例

  • 跨整個叢集,將 "cluster-admin" ClusterRole 中的權限授與給名為 "root" 的使用者

    kubectl create clusterrolebinding root-cluster-admin-binding --clusterrole=cluster-admin --user=root
    
  • 跨整個叢集,將 "system:node-proxier" ClusterRole 中的權限授與給名為 "system:kube-proxy" 的使用者

    kubectl create clusterrolebinding kube-proxy-binding --clusterrole=system:node-proxier --user=system:kube-proxy
    
  • 跨整個叢集,將 "view" ClusterRole 中的權限授與給 "acme" 命名空間中名為 "myapp" 的服務帳戶

    kubectl create clusterrolebinding myapp-view-binding --clusterrole=view --serviceaccount=acme:myapp
    

kubectl auth reconcile

從清單檔案建立或更新 rbac.authorization.k8s.io/v1 API 物件。

如果遺失物件,則會建立這些物件,並且如果需要,則會為命名空間物件建立包含命名空間。

現有的角色會更新為包含輸入物件中的權限,如果指定了 --remove-extra-permissions,則會移除額外的權限。

現有的繫結會更新為包含輸入物件中的主體,如果指定了 --remove-extra-subjects,則會移除額外的主體。

範例

  • 測試套用 RBAC 物件的清單檔案,顯示將進行的變更

    kubectl auth reconcile -f my-rbac-rules.yaml --dry-run=client
    
  • 套用 RBAC 物件的清單檔案,保留任何額外的權限 (在角色中) 和任何額外的主體 (在繫結中)

    kubectl auth reconcile -f my-rbac-rules.yaml
    
  • 套用 RBAC 物件的清單檔案,移除任何額外的權限 (在角色中) 和任何額外的主體 (在繫結中)

    kubectl auth reconcile -f my-rbac-rules.yaml --remove-extra-subjects --remove-extra-permissions
    

ServiceAccount 權限

預設 RBAC 原則將範圍權限授與給控制平面組件、節點和控制器,但將權限授與給 kube-system 命名空間之外的服務帳戶 (超出 API 探索角色授予的權限)。

這允許您根據需要將特定角色授與給特定的 ServiceAccount。細緻的角色繫結提供更高的安全性,但需要更多的管理工作。更廣泛的授與可能會為 ServiceAccount 提供不必要 (且可能升級) 的 API 存取權限,但更易於管理。

從最安全到最不安全的順序,方法如下

  1. 將角色授與給應用程式特定的服務帳戶 (最佳實務)

    這需要應用程式在其 Pod 規格中指定 serviceAccountName,並建立服務帳戶 (透過 API、應用程式清單檔案、kubectl create serviceaccount 等)。

    例如,在 "my-namespace" 內將唯讀權限授與給 "my-sa" 服務帳戶

    kubectl create rolebinding my-sa-view \
      --clusterrole=view \
      --serviceaccount=my-namespace:my-sa \
      --namespace=my-namespace
    
  2. 將角色授與給命名空間中的 "default" 服務帳戶

    如果應用程式未指定 serviceAccountName,則會使用 "default" 服務帳戶。

    例如,在 "my-namespace" 內將唯讀權限授與給 "default" 服務帳戶

    kubectl create rolebinding default-view \
      --clusterrole=view \
      --serviceaccount=my-namespace:default \
      --namespace=my-namespace
    

    許多附加元件kube-system 命名空間中的 "default" 服務帳戶身分執行。若要允許這些附加元件以超級使用者存取權限執行,請將叢集管理員權限授與給 kube-system 命名空間中的 "default" 服務帳戶。

    kubectl create clusterrolebinding add-on-cluster-admin \
      --clusterrole=cluster-admin \
      --serviceaccount=kube-system:default
    
  3. 將角色授與給命名空間中的所有服務帳戶

    如果您希望命名空間中的所有應用程式都具有角色,無論它們使用哪個服務帳戶,您都可以將角色授與給該命名空間的服務帳戶群組。

    例如,在 "my-namespace" 內將唯讀權限授與給該命名空間中的所有服務帳戶

    kubectl create rolebinding serviceaccounts-view \
      --clusterrole=view \
      --group=system:serviceaccounts:my-namespace \
      --namespace=my-namespace
    
  4. 將有限的角色授與給叢集範圍內的所有服務帳戶 (不建議)

    如果您不想管理每個命名空間的權限,您可以將叢集範圍的角色授與給所有服務帳戶。

    例如,跨所有命名空間將唯讀權限授與給叢集中所有服務帳戶

    kubectl create clusterrolebinding serviceaccounts-view \
      --clusterrole=view \
     --group=system:serviceaccounts
    
  5. 將超級使用者存取權限授與給叢集範圍內的所有服務帳戶 (強烈不建議)

    如果您完全不在意分割權限,您可以將超級使用者存取權限授與給所有服務帳戶。

    kubectl create clusterrolebinding serviceaccounts-cluster-admin \
      --clusterrole=cluster-admin \
      --group=system:serviceaccounts
    

EndpointSlices 和 Endpoints 的寫入存取權限

在 Kubernetes v1.22 之前建立的 Kubernetes 叢集在彙總的 "edit" 和 "admin" 角色中包含對 EndpointSlices (和 Endpoints) 的寫入存取權限。作為 CVE-2021-25740 的緩解措施,此存取權限不屬於您使用 Kubernetes v1.22 或更高版本建立的叢集中的彙總角色。

已升級至 Kubernetes v1.22 的現有叢集將不受此變更影響。CVE 公告包含限制現有叢集中此存取權的指南。

如果您希望新的叢集在聚合角色中保留此存取權層級,您可以建立以下 ClusterRole

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  annotations:
    kubernetes.io/description: |-
      Add endpoints write permissions to the edit and admin roles. This was
      removed by default in 1.22 because of CVE-2021-25740. See
      https://issue.k8s.io/103675. This can allow writers to direct LoadBalancer
      or Ingress implementations to expose backend IPs that would not otherwise
      be accessible, and can circumvent network policies or security controls
      intended to prevent/isolate access to those backends.
      EndpointSlices were never included in the edit or admin roles, so there
      is nothing to restore for the EndpointSlice API.      
  labels:
    rbac.authorization.k8s.io/aggregate-to-edit: "true"
  name: custom:aggregate-to-edit:endpoints # you can change this if you wish
rules:
  - apiGroups: [""]
    resources: ["endpoints"]
    verbs: ["create", "delete", "deletecollection", "patch", "update"]

從 ABAC 升級

最初執行舊版 Kubernetes 的叢集通常使用寬鬆的 ABAC 策略,包括授予所有服務帳戶完整的 API 存取權。

預設 RBAC 原則將範圍權限授與給控制平面組件、節點和控制器,但將權限授與給 kube-system 命名空間之外的服務帳戶 (超出 API 探索角色授予的權限)。

雖然安全性更高,但這可能會對期望自動接收 API 權限的現有工作負載造成干擾。以下是管理此轉換的兩種方法

並行授權器

同時執行 RBAC 和 ABAC 授權器,並指定包含舊版 ABAC 策略的策略檔案

--authorization-mode=...,RBAC,ABAC --authorization-policy-file=mypolicy.json

詳細說明第一個命令列選項:如果先前的授權器(例如 Node)拒絕請求,則 RBAC 授權器會嘗試授權 API 請求。如果 RBAC 也拒絕該 API 請求,則會接著執行 ABAC 授權器。這表示任何請求只要符合 RBAC 或 ABAC 策略其中之一,就會被允許。

當 kube-apiserver 在 RBAC 組件的日誌層級為 5 或更高時執行 (--vmodule=rbac*=5--v=5),您可以在 API 伺服器日誌中看到 RBAC 拒絕訊息(前綴為 RBAC)。您可以使用該資訊來判斷哪些角色需要授予哪些使用者、群組或服務帳戶。

一旦您將角色授予服務帳戶,且工作負載在伺服器日誌中沒有 RBAC 拒絕訊息的情況下執行,您就可以移除 ABAC 授權器。

寬鬆的 RBAC 權限

您可以使用 RBAC 角色綁定來複製寬鬆的 ABAC 策略。

在您轉換為使用 RBAC 之後,您應該調整叢集的存取控制,以確保這些控制符合您的資訊安全需求。

上次修改時間:2024 年 10 月 18 日下午 3:31 PST:KEP-3221:將 StructuredAuthorizationConfiguration 升級為 GA (32aad9dd3f)