date: 2020-08-13title: k8s学习—RBAC授权接口 #标题
tags: RBAC接口 #标签
categories: k8s # 分类

Role-based access control(RBAC)基于角色的访问控制,是k8s中支持的一种授权方式,使用rbac.authorization.k8s.io API 来驱动授权决策,允许管理员通过此API动态配置授权策略。
如果要激活 RBAC,在启动 API Server 时必须使用参数 —authorization-mode=RBAC,大多数部署文档,都有此参数,如下:

  1. $ kubectl get pods -A | grep api # 查看api的pod名称
  2. kube-system kube-apiserver-master 1/1 Running 1 23d
  3. $ kubectl edit pod/kube-apiserver-master -n kube-system # 查看api-server对应的yaml文件

找到 spec.containers.command 字段,如下(看到 —authorization-mode=Node,RBAC 配置项即可):

k8s学习--RBAC授权接口 - 图1

若没有上述字段,请自行添加,并删除pod(删除pod后会自动运行一个新的pod,相当于重启)。

Role和ClusterRole

在 RBAC API 中,角色包含了一组授权规则。此处的授权规则是纯粹的“授予”规则(没有“否定”规则)。角色可以用以下两种形式定义:

  • 名称空间中的 Role。
  • 集群范围内的 ClusterRole。

Role只能用来授权访问单个名称空间内部资源,如下,定义role授权读取default空间中的Pod:

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

ClusterRole 可以用来授予与 Role 相同的权限,但是由于 ClusterRole 是集群范围内的,也可以用来授权访问如下资源:

  • 集群范围内的资源(例如节点)
  • 非资源性质的端口(例如 “/healthz”)
  • 所有名称空间内的资源(例如 Pod,授权后可以使用这类语句 kubectl get pods —all-namespaces)

下面的 ClusterRole 可以授权读取任意特定名称空间的 secrets,或所有名称空间的 secrets(取决于如何 绑定):

  1. apiVersion: rbac.authorization.k8s.io/v1
  2. kind: ClusterRole
  3. metadata:
  4. # "namespace" omitted since ClusterRoles are not namespaced
  5. name: secret-reader
  6. rules:
  7. - apiGroups: [""]
  8. resources: ["secrets"]
  9. verbs: ["get", "watch", "list"]

RoleBinding和ClusterRoleBinding

角色绑定将角色中定义的权限授予给一个用户或者一组用户。角色绑定包含了一个被授权对象的列表(user、group、service account),以及一个被授予的角色的引用。

角色绑定有如下两种定义方式:

  • 名称空间内的 RoleBinding
  • 集群范围内的 ClusterRoleBinding

RoleBinding 可以引用同名称空间下的 Role。下面的 RoleBinding 将 “default” 名称空间中的角色 “pod-reader” 授予给用户 “lvjianzhao”,此时 “lvjianzhao” 可以读取 “default” 名称空间中的 pod。

  • roleRef:引用被授予的角色
  • kind 可以是 Role 或者 ClusterRole
  • name 是被引用的 Role 或者 ClusterRole 的名称

下面的 RoleBinding 使用 roleRef 将用户 “jane” 绑定到上面创建的 pod-reader 这个 Role:

  1. apiVersion: rbac.authorization.k8s.io/v1
  2. # This role binding allows "jane" to read pods in the "default" namespace.
  3. kind: RoleBinding
  4. metadata:
  5. name: read-pods
  6. namespace: default
  7. subjects:
  8. - kind: User
  9. name: jane # Name is case sensitive
  10. apiGroup: rbac.authorization.k8s.io
  11. roleRef:
  12. kind: Role #this must be Role or ClusterRole
  13. name: pod-reader # this must match the name of the Role or ClusterRole you wish to bind to
  14. apiGroup: rbac.authorization.k8s.io

RoleBinding 也可以引用一个 ClusterRole,用来授予 RoleBinding 所在名称空间中的对象的访问权限。这样,我们可以在集群内定义一组通用的角色,并且在不同的名称空间中重用这些角色。

例如,尽管下面的 RoleBinding 引用了 ClusterRole,“dave”(被授权的用户)也将只能够读取 “development” 名称空间(RoleBinding所在的名称空间)中的 secrets 对象。

  1. apiVersion: rbac.authorization.k8s.io/v1
  2. # This role binding allows "dave" to read secrets in the "development" namespace.
  3. kind: RoleBinding
  4. metadata:
  5. name: read-secrets
  6. namespace: development # This only grants permissions within the "development" namespace.
  7. subjects:
  8. - kind: User
  9. name: dave # Name is case sensitive
  10. apiGroup: rbac.authorization.k8s.io
  11. roleRef:
  12. kind: ClusterRole
  13. name: secret-reader
  14. apiGroup: rbac.authorization.k8s.io

ClusterRoleBinding 可以被用来授权访问集群级别的资源,以及所有名称空间中的资源。下面的 ClusterRoleBinding 允许 “manager” 用户组中的用户读取任何名称空间中的 secrets:

  1. apiVersion: rbac.authorization.k8s.io/v1
  2. # This cluster role binding allows anyone in the "manager" group to read secrets in any namespace.
  3. kind: ClusterRoleBinding
  4. metadata:
  5. name: read-secrets-global
  6. subjects:
  7. - kind: Group
  8. name: manager # Name is case sensitive
  9. apiGroup: rbac.authorization.k8s.io
  10. roleRef:
  11. kind: ClusterRole
  12. name: secret-reader
  13. apiGroup: rbac.authorization.k8s.io

RoleBinding、ClusterRoleBinding 创建后,其 roleRef 字段不可修改,如果尝试修改则会报错。如果需要修改 roleRef 字段,必须将 RoleBinding 或 ClusterRoleBinding 删除后重新创建。

这样做的主要原因有如下两点:

  • roleRef 不同的话,本质上是完全不同的绑定关系。要求删除并重建 RoleBinding 或 ClusterRoleBinding 以修改 roleRef 字段,可以确保列表中的被授权的对象(用户、用户组、Service Account)都是经过考虑的(如果直接修改 roleRef 字段,用户将不会核对列表中的用户、用户组、Service Account是否应该被授予新的角色)
  • 不允许修改 roleRef 字段的情况下,可以将修改 RoleBinding、ClusterRoleBinding 的权限授予给某个用户,使其可以管理其中的被授权对象列表(用户、用户组、Service Account),但是不能够修改对应的角色(权限)。

kubectl auth reconcile 命令行工具可以创建或更新包含 RBAC 对象的描述文件,删除、重新创建 RoleBinding、ClusterRoleBinding。

Referring to Resources

大多数的资源都以其名称作为标识,例如 “pods”,与其 API 的 URL 路径中的标识相同。某些 K8s API 也包含了 “subresource 子资源”,例如 pod 的 logs。其 API 的 URL 如下所示:

  1. apiVersion: rbac.authorization.k8s.io/v1
  2. kind: Role
  3. metadata:
  4. namespace: default
  5. name: pod-and-pod-logs-reader
  6. rules:
  7. - apiGroups: [""]
  8. resources: ["pods", "pods/log"]
  9. verbs: ["get", "list"]

对于某些请求,也可以使用 resourceNames 列表来引用其实例。此时,可以限定被访问的单个对象实例 。例如,下面的 yaml 可以授权对单个 configmap 进行 “get” 和 “update” 操作:

  1. apiVersion: rbac.authorization.k8s.io/v1
  2. kind: Role
  3. metadata:
  4. namespace: default
  5. name: configmap-updater
  6. rules:
  7. - apiGroups: [""]
  8. resources: ["configmaps"]
  9. resourceNames: ["my-configmap"]
  10. verbs: ["update", "get"]

注:“create” 操作不能通过 resourceName 来限定,因为该对象的名字在授权的时候还不存在;“deletecollection” 操作也不能通过 resourceName 来限定。

Aggregated ClusterRoles(聚合clusteroles)

从k8s 1.9开始,可以使用aggregationRule 来将 ClusterRole 与其他的 ClusterRole 合并。Aggregated ClusterRole 的权限由控制器管理,是所有与其 label selector 匹配的 ClusterRole 中所定义权限的并集。下面是一个 aggregated ClusterRole 的例子:

  1. apiVersion: rbac.authorization.k8s.io/v1
  2. kind: ClusterRole
  3. metadata:
  4. name: monitoring
  5. aggregationRule:
  6. clusterRoleSelectors:
  7. - matchLabels:
  8. rbac.example.com/aggregate-to-monitoring: "true"
  9. rules: [] # 控制器管理器自动填充规则。

创建一个与 aggregated ClusterRole 的 label selector 匹配的 ClusterRole 时,将会向该 aggregated ClusterRole 添加规则。在上面的例子中,可以向通过创建另外一个包含标签 rbac.example.com/aggregate-to-monitoring: true 的 ClusterRole 向名称为 “monitoring” 的 ClusterRole 添加规则:

  1. apiVersion: rbac.authorization.k8s.io/v1
  2. kind: ClusterRole
  3. metadata:
  4. name: monitoring-endpoints
  5. labels:
  6. rbac.example.com/aggregate-to-monitoring: "true"
  7. # 这些规则将被添加到“monitoring”角色中。
  8. rules:
  9. - apiGroups: [""]
  10. resources: ["services", "endpoints", "pods"]
  11. verbs: ["get", "list", "watch"]

默认的面向用户的角色是 aggregated ClusterRole。这样,我们就可以为默认角色添加 custom resource 的规则,例如 CustomResourceDefinition。

例如,下面的 ClusterRole 允许 “admin” 和 “edit” 这两个默认角色管理 custom resource “CronTabs”,而 “view” 角色则只能读取这些资源。

  1. apiVersion: rbac.authorization.k8s.io/v1
  2. kind: ClusterRole
  3. metadata:
  4. name: aggregate-cron-tabs-edit
  5. labels:
  6. # Add these permissions to the "admin" and "edit" default roles.
  7. rbac.authorization.k8s.io/aggregate-to-admin: "true"
  8. rbac.authorization.k8s.io/aggregate-to-edit: "true"
  9. rules:
  10. - apiGroups: ["stable.example.com"]
  11. resources: ["crontabs"]
  12. verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
  13. ---
  14. kind: ClusterRole
  15. apiVersion: rbac.authorization.k8s.io/v1
  16. metadata:
  17. name: aggregate-cron-tabs-view
  18. labels:
  19. # Add these permissions to the "view" default role.
  20. rbac.authorization.k8s.io/aggregate-to-view: "true"
  21. rules:
  22. - apiGroups: ["stable.example.com"]
  23. resources: ["crontabs"]
  24. verbs: ["get", "list", "watch"]

role 模板

  1. # 注: 以下只是展示了rules这一部分
  2. # 允许读取 core api group 中的pods
  3. rules:
  4. - apiGroups: [""]
  5. resources: ["pods"]
  6. verbs: ["get", "list", "watch"]
  7. # 允许 读取/写入 “extensions” 和 “apps” API Group 中的 “deployments”:
  8. rules:
  9. - apiGroups: ["extensions", "apps"]
  10. resources: ["deployments"]
  11. verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
  12. # 允许读取 “pods”、读取/写入 “jobs”:
  13. rules:
  14. - apiGroups: [""]
  15. resources: ["pods"]
  16. verbs: ["get", "list", "watch"]
  17. - apiGroups: ["batch", "extensions"]
  18. resources: ["jobs"]
  19. verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
  20. # 允许读取名为 “my-config” 的 ConfigMap(必须绑定到某个名称空间中的 RoleBinding):
  21. rules:
  22. - apiGroups: [""]
  23. resources: ["configmaps"]
  24. resourceNames: ["my-config"]
  25. verbs: ["get"]
  26. # 允许读取 core API Group 中的 “nodes”(由于节点时集群级别的对象,此规则必须定义在 ClusterRole 中:
  27. rules:
  28. - apiGroups: [""]
  29. resources: ["nodes"]
  30. verbs: ["get", "list", "watch"]
  31. # 允许对非资源型的端口 “/healthz”(及其所有子路径)执行 “GET” 和 “POST” 请求
  32. # (此规则必须定义在 ClusterRole 中):
  33. rules:
  34. - nonResourceURLs: ["/healthz", "/healthz/*"]
  35. verbs: ["get", "post"]

Referring to Subjects

RoleBinding、ClusterRoleBinding 将角色绑定到被授权主体。被授权主体可以是 group、user、service account。

User 通过 string 来标识,可以是普通的 username,例如 “alice”,email风格的名称,例如“bob@example.com”,或者以字符数形式定义的数字ID。由我们通过配置 authentication modules 来决定产生何种格式的 username,RBAC 授权系统对此做限定。但是,system: 前缀是被 K8s 系统预留的,应该确保 username 不包含这一前缀。

K8s 中的 Group 信息由 Authenticator 模块提供。与 user 一样,group 也使用 string 来标识,system: 前缀也是被预留的,但是没有格式要求。

Service Account 使用 system:serviceaccount: 前缀的 username,并且属于 system:serviceaccounts: 前缀的 group。

Role Binding 模板

  1. # 下面的例子中只显示了 RoleBinding、ClusterRoleBinding 的 subjects 部分。
  2. # 绑定 user “alice@example.com”:
  3. subjects:
  4. - kind: User
  5. name: "alice@example.com"
  6. apiGroup: rbac.authorization.k8s.io
  7. # 绑定 group “frontend-admins”:
  8. subjects:
  9. - kind: Group
  10. name: "frontend-admins"
  11. apiGroup: rbac.authorization.k8s.io
  12. # 绑定 kube-system 名称空间中的 default service account:
  13. subjects:
  14. - kind: ServiceAccount
  15. name: default
  16. namespace: kube-system
  17. # 绑定 qa 名称空间中的所有 service account:
  18. subjects:
  19. - kind: Group
  20. name: system:serviceaccounts:qa
  21. apiGroup: rbac.authorization.k8s.io
  22. # 绑定任意 service account:
  23. subjects:
  24. - kind: Group
  25. name: system:serviceaccounts
  26. apiGroup: rbac.authorization.k8s.io
  27. # 绑定所有已认证的用户:
  28. subjects:
  29. - kind: Group
  30. name: system:authenticated
  31. apiGroup: rbac.authorization.k8s.io
  32. # 绑定所有未认证用户
  33. subjects:
  34. - kind: Group
  35. name: system:unauthenticated
  36. apiGroup: rbac.authorization.k8s.io
  37. # 绑定所有用户
  38. subjects:
  39. - kind: Group
  40. name: system:authenticated
  41. apiGroup: rbac.authorization.k8s.io
  42. - kind: Group
  43. name: system:unauthenticated
  44. apiGroup: rbac.authorization.k8s.io