原创译文 转载请标明出处
[TOC]
简介
基于角色的权限控制,使用 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 部分
引用 [email protected] 的 subject 部分
subjects:
- kind: User
name: "[email protected]"
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 ClusterRole | Default ClusterRoleBinding | Description 描述 |
---|---|---|
system:basic-user | system:authenticated and system:unauthenticated groups | 只允许用户读取自身的基础信息 |
system:discovery | system: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 ClusterRole | Default ClusterRoleBinding | Description 描述 |
---|---|---|
cluster-admin | system:masters group | 允许在任何资源上执行任何操作,当通过ClusterRoleBinding 使用此角色时,授权所有民命空间下的所有资源,当使用 Rolebinding 时,授权rolebingding 所在的 命名空间下的所有资源,并包含命名空间自身所代表的资源 |
admin | None | 允许管理员访问,一般与Rolebinding搭配使用,绑定到一个命名空间中,可以读写大多数命名空间中的资源,并且可以在命名空间中创建 role 和 rolebinding,不允许访问命名空间中的资源配额,和命名空间自身 |
edit | None | 允许读写命名空间中的大多数资源,不过不允许查看和修改角色 (role)和角色绑定 (role binding) |
view | None | 允许读命名空间中的大多数资源,不过不允许查看和修改角色 (role)和角色绑定 (role binding),不允许查看secrets 资源 |
核心组件角色 Core Component Roles
Default ClusterRole | Default ClusterRoleBinding | Description 描述 |
---|---|---|
system:kube-scheduler | system:kube-scheduler user | 允许访问 kube-scheduler 组件所需的资源 |
system:kube-controller-manager | system:kube-controller-manager user | 允许访问 kube-controller-manager 组件所需的资源,控制器角色中包含单个控制循环所需的权限。 |
system:node | system:nodes group (deprecated in 1.7) | 允许访问kubelet组件所需的资源,包括对所有秘密的读取访问权限,以及对所有pod的访问权限。在1.7版本中,推荐使用 Node authorizer 和 NodeRestriction admission plugin 替代这个角色,并且允许根据pod的调度情况来授予对kubelet的API访问权限,从1.7开始,当启用“Node”授权模式时,不会自动绑定到“system:nodes”组 |
system:node-proxier | system:kube-proxy user | 允许访问kube-proxy组件所需的资源 |
其他组件角色 (other Component Roles)
Default ClusterRole | Default ClusterRoleBinding | Description 描述 |
---|---|---|
system:auth-delegator | None | 允许代理认证和授权,一般用途是作为 api server 的插件的唯一认证与授权 |
system:heapster | None | heapster组件相关的角色 |
system:kube-aggregator | None | kube-aggregator 组件相关的角色 |
system:kube-dns | kube-dns service account in the kube-system namespace | kube-dns 组件相关的角色 |
system:node-bootstrapper | None | 允许访问执行Kubelet TLS bootstrap 需的资源。 |
system:node-problem-detector | None | node-problem-detector 组件相关的角色 |
system:persistent-volume-provisioner | None | 允许访问大多数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。要让一个用户创建/更新角色
授予用户一个角色,允许他们根据需要创建/更新Role或ClusterRole对象。
授予用户你希望他们在创建角色时,可以指定的权限。如果他们试图创建拥有其自身没有权限的角色(role)或者集群角色(cluster role),API 请求会自行阻止。
用户只能对其角色拥有的权限创建 role binding(在和role binding 相同的范围内),或者在其被显示授权(been given explicit permission)可以对某个角色进行binding 时才能创建。例如,如果user1 没有读取集群范围内secret的权限,那么user1 就不能创建拥有读取集群范围内secret 权限 的 role 的ClusterRoleBinding。要让一个用户创建/更新角色绑定
授予他们一个角色允许根据需要创建 Rolebinding 或者ClusterRoleBinding 对象。
授予他们必要的权限来绑定具体的角色(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访问权限,但是更容易管理。
从最安全到最不安全的方法是:
- 为应用程序特定的服务帐户授予角色 (最佳实践)
这要求应用程序在其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
- 在命名空间中为“默认”服务帐户(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
- 为命名空间中的所有服务帐户授予角色
如果希望命名空间中的所有应用程序都具有角色,无论使用什么服务帐户,您可以将角色授予该名称空间的服务帐户组。
例如,将“my-namespace”中的只读权限授予该命名空间中的所有服务帐户
kubectl create rolebinding serviceaccounts-view \
--clusterrole=view \
--group=system:serviceaccounts:my-namespace \
--namespace=my-namespace
- 对集群范围内的所有服务帐户(不鼓励)授予权限(role)
如果您不想为每个命名空间管理权限,可以将群集范围的角色(ClusterRole)授予所有服务帐户。
例如,将所有命名空间中的只读权限授予群集中的所有服务帐户:
kubectl create clusterrolebinding serviceaccounts-view \
--clusterrole=view \
--group=system:serviceaccounts
- 将超级用户权限授予集群内的所有服务帐户(强烈反对)
如果您根本不关心权限问题,可以向所有服务帐户授予超级用户权限。
警告:这允许任何具有读取权限的用户访问 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