原创译文,转载请标明出处。

简介

基于角色的权限控制,使用 rbac.authorization.k8s.io API 组来驱动授权决策,允许管理员通过K8S API 来动态的配置安全策略

RBAC 模式在1.6版本仍然是BETA 状态,要启用RBAC 需要在API SERVER的启动参数中添加

--authorization-mode=RBAC

API 概览

此章节包含 RBAC API 声明的四种顶层类型。用户可以像使用其他API 资源(resource)(通过kubectl,API调用等)一样来使用这些资源进行交互。 比如kubectl -f (resource).yaml ,这种形式,也可以用于本章节的权限资源

角色与集群角色(role and cluster role)

在 RBAC API 中, 角色包含了一组代表权限的规则,权限声明只有单纯的允许声明,没有某种权限申明为拒绝访问的申明形式。一个角色可以使用Role 类型定义到一个namespace 中。或者也可以使用ClusterRole 类型定义到整个急群众

一个Role 类型的角色只能访问其所在的namespace的资源,例如如下例子定义了一个default namespace中读取pod 权限的角色

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

ClusterRole 类型的角色授权与Role 类型(kind)的角色相似。不过因为ClusterRole类型是集群范围,所以其还可以添加下列权限

  • 集群范围的资源(cluster-scope resource) 比如 nodes
  • 非资源类型的 endpoints (non-resource endpoints)比如 /healthz
  • 夸命名空间资源 (namespaced resource) 比如 kubectl get pod –all-namespaces

下面这个ClusterRole 可以读取某个具体namespace的secret 也可以读取所有明明空间的secret

kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  # "namespace" omitted since ClusterRoles are not namespaced
  name: secret-reader
rules:
- apiGroups: [""]
  resources: ["secrets"]
  verbs: ["get", "watch", "list"]

角色绑定与集群角色绑定(RoleBinding and ClusterRoleBinding)

角色绑定(Rolebinding)将角色(role)与用户(user)联系起来,角色绑定包含了一系列的子对象(users,groups,或者 service accounts),然后将这些对象连接到一个拥有某种授权的角色(role)上,Rolebinding 绑定某个具体namespace的角色(Role), ClusterRoleBinding,绑定 ClusterRole 类型的角色。

# This role binding allows "jane" to read pods in the "default" namespace.
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: read-pods
  namespace: default
subjects:
- kind: User
  name: jane
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

RoleBinding 也可以引用CulsterRole 来配置命名空间范围内的资源的访问策略,这种方式允许管理员定义一些针对namespace的通用的角色(我的理解是基础权限),然后重用此类型的ClusterRole 到某个具体的namespace中,而不必为每个namespace 建立独立的Role

比如下面这个例子,虽然引用了ClusterRole,但是其仍然只能访问Development 命名空间(RoleBinding 的namespace )内的资源

# This role binding allows "dave" to read secrets in the "development" namespace.
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: read-secrets
  namespace: development # This only grants permissions within the "development" namespace.
subjects:
- kind: User
  name: dave
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: secret-reader
  apiGroup: rbac.authorization.k8s.io

ClusterRoleBinding 用于授权集群范围内所有命名空间的权限。 下面的例子,允许manager 组内的所有用户,读取任何namespace 中的secret

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

引用资源 Referring to resource

大多数资源都是通过一个字符串来表示其自身的,比如 pods, 就先它在API URL 中的表现形式一样,尽管如此,某些 API 包含了子资源,比如 pod的log 他的 API URL 如下

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

这种情况下,log是pod的子资源,在RBAC 授权中,要表达这种关系,用反斜杠定义资源与子资源,要允许一个对象(subject) 读取pod 和pod 的日志,要如下书写Role 对象

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

资源出了通过类型名称(pods,secrets 等)进行引用之外,也可以用过资源名称(Resource name)引用某个具体的资源。同时,可以通过Verbs,限定在某个具体资源上的操作权限,例如

kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  namespace: default
  name: configmap-updater
rules:
- apiGroups: [""]
  resources: ["configmap"]
  resourceNames: ["my-configmap"]
  verbs: ["update", "get"]

verbs 限定了只能更新和读取 configmap 类型中的my-configmap 实例中的内容。

注意如果使用的resourceNames verbs 中的权限不能为 list, watch, create, deletecollection,因为资源名称不包含在create watch, create, deletecollection的API URL 中。

Role example

下面的例子只包含了rules 部分
允许在core api 组中读取pod

rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "list", "watch"]

允许在 extensions 和 apps ,API 组中读取和写入 deployments

rules:
- apiGroups: ["extensions", "apps"]
  resources: ["deployments"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]

允许读取 pod, 和在jobs 资源中读取写入

rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "list", "watch"]
- apiGroups: ["batch", "extensions"]
  resources: ["jobs"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]

允许读取 my-config (ConfigMap 类型的资源)实例的内容( 必须通过RoleBinding 绑定到一个具体的namespace,权限在此namespace 范围内生效)

rules:
- apiGroups: [""]
  resources: ["configmaps"]
  resourceNames: ["my-config"]
  verbs: ["get"]

允许在core api group中读取 nodes 资源 (因为node 是集群范围内的资源,所以必须使用ClusterRole 和ClusterRoleBingding来绑定才能生效)

rules:
- apiGroups: [""]
  resources: ["nodes"]
  verbs: ["get", "list", "watch"]

允许对非资源的 endpoint 和其subpath 使用“get”和“post”请求(必须使用ClusterRole 和ClusterRoleBingding来绑定才能生效)

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

引用对象(Reffering Subjects)

RoleBinding 和 ClusterRoleBinding 将 角色(role)绑定到对象(subject)上,对象(subject)可以是用户(user),组(group),或者 service account

用户可以通过字符来表示,其形式包含 一般用户名,email 形式的用户名,和数字id 形式的用户名,具体形式取决于管理员的配置。在RABC 授权系统中,并不要求某种具体的形式,但是前缀 system: 是一个保留字,所以用户名中不能包含此前缀。

组在K8S 中通过Authenticator modules 来提供,组(group) 和用户(user)一样,通过字符来表示。并且没有限定具体的形式,不过system: 仍然不能作为组名的前缀

Service Account 的用户名拥有 system:serviceaccount: 前缀,并且属于拥有 system:serviceaccounts (注意末尾的S)前缀的组

RoleBinding 例子
下面的例子只包含了RoleBinding 中的 subjects 部分
引用 alice@example.com 的 subject 部分

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

引用组 frontend-admins 的 subject 部分

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

kube-system 命名空间(namespace) 中,引用名为 default 的service account

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

引用 qa 命名空间中(namespace) 所有的service account

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

引用所有命名空间中的所有 service account

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

引用所有认证过的用户(user) 1.5 之后的版本适用

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

引用所有未通过认证的用户 1.5之后的版本适用

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

默认角色与角色绑定 (Default Roles and Role Bindings)

api server 创建了一系列的默认 ClusterRole 和 ClusterRoleBinding 对象, 其中许多对象以 system: 前缀开头,代表其中绑定的资源是作为基础设施适用和占有的。修改这些资源会导致整个集群不可用。一个例子是 system:node ClusterRole。这个角色拥有一系列的kubelet 权限,如果这个角色被修改了,可能会让kubelet 出现异常。

所有默认的集群角色 (ClusterRole) 和其角色绑定(role binding)都带有如下标记

kubernetes.io/bootstrapping=rbac-defaults

自动协调 Auto-reconciliation

在每次启动的时候, api server 会自动更新默认的集群角色(default cluster roles)的信息,添加缺少的权限和对象(user , group, service account 等),这个机制可以让集群自我修复,同时也可以让集群在role, role binding ,subject 发生变化的时候,自动同步更新到最新状态。

如果要退出自动协调,只需要在默认的cluster role 或者 role binding 中设置 rbac.authorization.kubernetes.io/autoupdate 声明 (annotation )为 false 即可。注意,缺少默认权限(permissions)或者对象(subjects) 会导致集群不可用

自动协调在 K8S 1.6+ 的版本中启用RBAC 授权时被激活。

发现角色 (Discovery Roles)

Default ClusterRoleDefault ClusterRoleBindingDescription 描述
system:basic-usersystem:authenticated and system:unauthenticated groups只允许用户读取自身的基础信息
system:discoverysystem:authenticated and system:unauthenticated groups只允许 api discovery endpoints 的读取权限并且需要 和一个API level 发现和协商

面向用户的角色 (User-facing Roles)

一些不带 system: 前缀的默认角色,是用来面向用户使用的。他们包含超级用户角色 (cluster-admin), 使用 ClusterRoleBinding 的集群范围的角色 (cluster-status), 以及是用RoleBding 的具体某个 namespace中的角色 (admin, edit, view)

Default ClusterRoleDefault ClusterRoleBindingDescription 描述
cluster-adminsystem:masters group允许在任何资源上执行任何操作,当通过ClusterRoleBinding 使用此角色时,授权所有民命空间下的所有资源,当使用 Rolebinding 时,授权rolebingding 所在的 命名空间下的所有资源,并包含命名空间自身所代表的资源
adminNone允许管理员访问,一般与Rolebinding搭配使用,绑定到一个命名空间中,可以读写大多数命名空间中的资源,并且可以在命名空间中创建 role 和 rolebinding,不允许访问命名空间中的资源配额,和命名空间自身
editNone允许读写命名空间中的大多数资源,不过不允许查看和修改角色 (role)和角色绑定 (role binding)
viewNone允许读命名空间中的大多数资源,不过不允许查看和修改角色 (role)和角色绑定 (role binding),不允许查看secrets 资源

核心组件角色 Core Component Roles

Default ClusterRoleDefault ClusterRoleBindingDescription 描述
system:kube-schedulersystem:kube-scheduler user允许访问 kube-scheduler 组件所需的资源
system:kube-controller-managersystem:kube-controller-manager user允许访问 kube-controller-manager 组件所需的资源,控制器角色中包含单个控制循环所需的权限。
system:nodesystem:nodes group (deprecated in 1.7)允许访问kubelet组件所需的资源,包括对所有秘密的读取访问权限,以及对所有pod的访问权限。在1.7版本中,推荐使用 Node authorizerNodeRestriction admission plugin 替代这个角色,并且允许根据pod的调度情况来授予对kubelet的API访问权限,从1.7开始,当启用“Node”授权模式时,不会自动绑定到“system:nodes”组
system:node-proxiersystem:kube-proxy user允许访问kube-proxy组件所需的资源

其他组件角色 (other Component Roles)

Default ClusterRoleDefault ClusterRoleBindingDescription 描述
system:auth-delegatorNone允许代理认证和授权,一般用途是作为 api server 的插件的唯一认证与授权
system:heapsterNoneheapster组件相关的角色
system:kube-aggregatorNonekube-aggregator 组件相关的角色
system:kube-dnskube-dns service account in the kube-system namespacekube-dns 组件相关的角色
system:node-bootstrapperNone允许访问执行Kubelet TLS bootstrap 需的资源。
system:node-problem-detectorNonenode-problem-detector 组件相关的角色
system:persistent-volume-provisionerNone允许访问大多数dynamic volume provisioners 所需的资源。

控制器角色 (Controller Roles)

Kubernetes控制器管理器运行核心控制环路。当使用 –use-service-account-credentials 参数调用时,每个控制循环都将使用单独的服务帐户(service account) 启动。对于每个控制循环中的角色都以system: 前缀开头。如果不是用 –use-service-account-credentials 参数,它将使用其自己的凭证运行所有控制循环,这些凭证必须包含所有相关的角色的权限。这些角色包括:

  • system:controller:attachdetach-controller
  • system:controller:certificate-controller
  • system:controller:cronjob-controller
  • system:controller:daemon-set-controller
  • system:controller:deployment-controller
  • system:controller:disruption-controller
  • system:controller:endpoint-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:replicaset-controller
  • system:controller:replication-controller
  • system:controller:resourcequota-controller
  • system:controller:route-controller
  • system:controller:service-account-controller
  • system:controller:service-controller
  • system:controller:statefulset-controller
  • system:controller:ttl-controlle

防止非法提权 (Privilege Escalation Prevention and Bootstrapping)

RBAC API 阻止用户通过编辑角色(Role)或角色绑定(role binding)来升级权限。因为这是在API级强制限定的,所以即使RBAC授权模式未被使用也适用。

用户只能创建自身所拥有的权限范围内的角色,即如果user1 没有读取集群范围内secret的权限,那么user1 就不能创建拥有这个权限的ClusterRole。要让一个用户创建/更新角色

  1. 授予用户一个角色,允许他们根据需要创建/更新Role或ClusterRole对象。

  2. 授予用户你希望他们在创建角色时,可以指定的权限。如果他们试图创建拥有其自身没有权限的角色(role)或者集群角色(cluster role),API 请求会自行阻止。

用户只能对其角色拥有的权限创建 role binding(在和role binding 相同的范围内),或者在其被显示授权(been given explicit permission)可以对某个角色进行binding 时才能创建。例如,如果user1 没有读取集群范围内secret的权限,那么user1 就不能创建拥有读取集群范围内secret 权限 的 role 的ClusterRoleBinding。要让一个用户创建/更新角色绑定

  1. 授予他们一个角色允许根据需要创建 Rolebinding 或者ClusterRoleBinding 对象。

  2. 授予他们必要的权限来绑定具体的角色(role)
    2.1. 隐式地,他们用后自己相关角色的绑定权限
    2.2. 显示地,可以授予他们某个具体角色的绑定权限(自身不一定拥有目标角色)

例如,下面这个例子允许 user1 在user-1-namespace 命名空间中授权其他用户(user) admin edit 和view 角色

apiVersion: rbac.authorization.k8s.io/v1beta1
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"]
  resourceNames: ["admin","edit","view"]
---
apiVersion: rbac.authorization.k8s.io/v1beta1
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

当创建(bootstrap)第一个角色和角色绑定时,初始用户必须授予他们尚未拥有的权限

创建初始角色和角色绑定
- 使用和system:masters 组中的账户,比如包含 cluster-admin super-user 等管理角色的账户
- 如果api server 没有使用安全端口(–insecure-port),你仍然能通过安全端口使用api(没有强制要求认证与授权)。

命令行工具 Command-line Utilities

两个kubectl 命令可以用来在命名空间范围或集群范围授权角色。

kubectl create rolebinding

在一个命名空间(namespace)中授权一个角色(Role)或者集群角色(ClusterRole),例子

  • 在acme 命名空间中,授权用户 bob admin 集群角色 (ClusterRole)
kubectl create rolebinding bob-admin-binding --clusterrole=admin --user=bob --namespace=acme
  • 在acme 命名空间中授权 名为 myapp的 service account view 集群角色
kubectl create rolebinding myapp-view-binding --clusterrole=view --serviceaccount=acme:myapp --namespace=acme

kubectl create clusterrolebinding

授权集群范围内的ClusterRole,包含namespace 权限。

授权 root 用户为 cluster-admin 的集群角色(ClusterRole)

kubectl create clusterrolebinding root-cluster-admin-binding --clusterrole=cluster-admin --user=root

授权kubelet 用户 system:node 角色

kubectl create clusterrolebinding kubelet-node-binding --clusterrole=system:node --user=kubelet

授权名为 myapp 的service account, view 角色

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

Service Account 权限 (Service Account Permissions)

默认RBAC策略向控制平面(controll plane),节点和控制器授予拥有范围限制的权限,但不向“kube-system”命名空间之外的服务帐户(service account)授予权限(超出所有已验证用户的发现权限)

这允许您根据需要向特定服务帐户授予特定角色。细粒度角色绑定提供更大的安全性,但需要更多的精力来管理。宽泛的授权可能给服务帐户提供不必要的(隐性提权)API访问权限,但是更容易管理。

从最安全到最不安全的方法是:

  1. 为应用程序特定的服务帐户授予角色 (最佳实践)

    这要求应用程序在其pod规范中指定serviceAccountName,并且要在之前创建好服务帐户(通过API,应用程序清单【application manifest】,kubectl 等方式创建)。
    例如,将“my-namespace”中的只读权限授予“my-sa”服务帐户:

    kubectl create rolebinding my-sa-view \
    --clusterrole=view \
    --serviceaccount=my-namespace:my-sa \
    --namespace=my-namespace
  2. 在命名空间中为“默认”服务帐户(service account)授予角色

    如果应用程序没有指定serviceAccountName,它将使用“默认”服务帐户。

    注意:授予“默认”服务帐户的权限可用于和任何命名空间内,未指定服务账户(service account) 的POD。

    例如,将“my-namespace”中的只读权限授予“默认”服务帐户:

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

    许多插件(add-on)使用“kube-system”命名空间中的“默认”服务帐户运行。要允许这些加载项使用超级用户访问权限,请将cluster-admin权限授予“kube-system”命名空间中的“默认”服务帐户

    注意:如果在kube-system命名空间内授予默认服务账户cluster-admin 权限,这意味着kube-system 拥有了super user的特权

    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. 对集群范围内的所有服务帐户(不鼓励)授予权限(role)
    如果您不想为每个命名空间管理权限,可以将群集范围的角色(ClusterRole)授予所有服务帐户。
    例如,将所有命名空间中的只读权限授予群集中的所有服务帐户:

    kubectl create clusterrolebinding serviceaccounts-view \
    --clusterrole=view \
    --group=system:serviceaccounts
  5. 将超级用户权限授予集群内的所有服务帐户(强烈反对)
    如果您根本不关心权限问题,可以向所有服务帐户授予超级用户权限。
    警告:这允许任何具有读取权限的用户访问 secret或创建一个pod以访问超级用户凭据。

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

从1.5升级 (Upgrading from 1.5)

在Kubernetes 1.6之前,许多部署(deployment)使用非常宽泛的ABAC策略,包括授予所有服务帐户完全的API访问权限。

默认RBAC策略向控制平面组件(controll plane component),节点(node)和控制器(controller)授予d带范围限制的权限,但不向“kube-system”命名空间之外的服务帐户授予权限(超出已验证用户的发现权限)。

虽然安全性更高,但这可能会影响到期望自动接收API权限的现有工作负载。以下是做此转换的两种方法

并行授权者

同时运行RBAC和ABAC授权器,并包括旧版ABAC策略:

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

RBAC授权者将尝试首先授权请求。如果它拒绝API请求,则ABAC授权器接过请求的授权任务。这意味着RBAC或ABAC其中之一允许请求即可。

当日志级别为2或更高(-v = 2)运行时,您可以在apiserver日志中看到RBAC的拒绝日志(以RBAC DENY : 为前缀)。您可以使用该信息来确定哪些角色需要授予哪些用户(user),组(group)或服务帐户(service account)。一旦向服务帐户授予角色,并且在服务器日志中没有RBAC拒绝消息的工作负载正在运行,则可以删除ABAC授权器

灵活的RBAC权限(Permissive RBAC Permissions)

您可以使用RBAC角色绑定来复制一个允许的策略。
警告:以下策略允许所有服务帐户充当集群管理员。运行在容器中的任何应用程序都会自动接收服务帐户凭据,并且可以针对API执行任何操作,包括查看secret和修改权限。这是不推荐的策略。

kubectl create clusterrolebinding permissive-binding \
  --clusterrole=cluster-admin \
  --user=admin \
  --user=kubelet \
  --group=system:serviceaccounts

英文连接:https://kubernetes.io/docs/admin/authorization/rbac/#referring-to-subjects

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐