K8s 基于角色的访问控制 RBAC

基于角色的访问控制(Role-Based Access Control, 即“RBAC”)使用 “rbac.authorization.k8s.io” API Group 实现授权控制,用户可以通过 Kubernetes API 动态配置策略。

API 对象

RBAC 共包含4个类型的资源对象:Role、ClusterRole、RoleBinding、ClusterRoleBinding。用户可以通过增删改查上述四个API对象来实现访问权限的动态控制。

假如没有创建任何ClusterRole和Role,则所有用户是无权限访问任何K8S的API的,K8S的权限控制是类似于白名单的,通过创建 Role&RoleBinding 和 ClusterRole&ClusterRoleBinding 将用户权限添加到“白名单”中,以此来实现授权。

Role 和 ClusterRole

在 RBAC API 中,Role 和 Cluster 都表示一组权限的集合,Role 是 namespace-scoped的,定义的是某一个namespace中的资源权限;而如果想要实现集群级别的或者跨namespace的权限控制,则需要创建 ClusterRole。

Role example

如上文所说,Role 是 namespace-scoped的,定义的是某一个namespace中的资源权限。

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"]

上述 pod-reader role,表示可以get/list/watch default namespce下面的pods资源。

Role 中可以定义多条rules,每条rule表示一个权限,rule类型定义如下:

type Rule struct {
	// Verbs is a list of Verbs that apply to ALL the ResourceKinds and AttributeRestrictions contained in this rule.  VerbAll represents all kinds.
	Verbs []string

	// APIGroups is the name of the APIGroup that contains the resources.
	// If multiple API groups are specified, any action requested against one of the enumerated resources in any API group will be allowed.
	APIGroups []string
	// Resources is a list of resources this rule applies to.  '*' represents all resources in the specified apiGroups.
	// '*/foo' represents the subresource 'foo' for all resources in the specified apiGroups.
	Resources []string
	// ResourceNames is an optional white list of names that the rule applies to.  An empty set means that everything is allowed.
	ResourceNames []string

	// NonResourceURLs is a set of partial urls that a user should have access to.  *s are allowed, but only as the full, final step in the path
	// If an action is not a resource API request, then the URL is split on '/' and is checked against the NonResourceURLs to look for a match.
	// Since non-resource URLs are not namespaced, this field is only applicable for ClusterRoles referenced from a ClusterRoleBinding.
	// Rules can either apply to API resources (such as "pods" or "secrets") or non-resource URL paths (such as "/api"),  but not both.
	NonResourceURLs []string
}

ClusterRole example

ClusterRole 是用来实现集群级别的或者跨namespace的权限控制:

  • cluster-scoped 类型的资源,比如nodes
  • non-resource 类型的api,比如/healthz`
  • namespace-scoped 类型的资源,实现跨namespace的权限控制
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"]

secret-reader 表示 get/list/watch 所有namespaces下面的secrets资源的权限。

RoleBinding 和 ClusterRoleBinding

Role 和 ClusterRole 都表示了权限的集合,权限只有授予某个user或者group才有实际意义。权限和用户之间的关联关系 是通过 RoleBinding 和 ClusterRoleBinding 两个API资源来实现的。RoleBinding 是 namespace-scoped的,而 ClusterRoleBinding是 cluster-scoped的。

RoleBinding example

RoleBinding 可以引用在同一命名空间内定义的 Role 对象。 下面示例中定义的 RoleBinding 对象在“default” 命名空间中将“pod-reader” 角色授予用户“jane”。 这一授权将允许用户“jane” 从“default” 命名空间中读取 pod。

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 对象也可以引用一个 ClusterRole 对象用于在 RoleBinding 所在的命名空间内授予用户对所引用的 ClusterRole 中 定义的命名空间资源的访问权限。这一点允许管理员在整个集群范围内首先定义一组通用的角色,然后再在不同的命名空间中复用这些角色。

例如,尽管下面示例中的 RoleBinding 引用的是一个 ClusterRole 对象,但是用户”dave”(即角色绑定主体)还是只能读取”development” 命名空间中的 secret(即 RoleBinding 所在的命名空间)。

# 以下角色绑定允许用户 "dave" 读取 "development" 命名空间中的 secret。
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: read-secrets
  namespace: development # 这里表明仅授权读取 "development" 命名空间中的资源。
subjects:
- kind: User
  name: dave
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: secret-reader
  apiGroup: rbac.authorization.k8s.io

ClusterRoleBinding example

可以使用ClusterRoleBinding在集群级别和所有命名空间中授予权限。下面示例中所定义的ClusterRoleBinding允许在用户组”manager” 中的任何用户都可以读取集群中任何命名空间中的 secret。

以下 ClusterRoleBinding 对象允许在用户组 "manager" 中的任何用户都可以读取集群中任何命名空间中的 secret。

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

更多类型的资源引用

大多数资源由代表其名字的字符串表示,例如”pods”,就像它们出现在相关 API endpoint 的 URL 中一样。然而,有一些 Kubernetes API 还 包含了” 子资源”,比如 pod 的 logs。在 Kubernetes 中,pod logs endpoint 的 URL 格式为:

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

在这种情况下,“pods” 是命名空间资源,而“log” 是 pods 的子资源。为了在 RBAC 角色中表示出这一点,我们需要使用斜线来划分资源 与子资源。如果需要角色绑定主体读取 pods 以及 pod log,您需要定义以下角色:

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"]

通过resourceNames列表,角色可以针对不同种类的请求根据资源名引用资源实例。当指定了resourceNames列表时,不同动作 种类的请求的权限,如使用get、delete、update、patch 等动词的请求,将被限定到资源列表中所包含的资源实例上。 例如,如果需要限定一个角色绑定主体只能“get” 或者“update” 一个 configmap 时,您可以定义以下角色:

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

值得注意的是,如果设置了resourceNames,则请求所使用的动词不能是 list、watch、create 或者 deletecollection。 由于资源名不会出现在 create、list、watch 和 deletecollection 等 API 请求的 URL 中,所以这些请求动词不会被设置了resourceNames的规则所允许,因为规则中的resourceNames 部分不会匹配这些请求。

更多示例

角色定义示例

  • 允许读取 core API Group 中定义的资源 pods:
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "list", "watch"]
  • 允许读写在 extensions 和 apps API Group 中定义的 deployments :
rules:
- apiGroups: ["extensions", "apps"]
  resources: ["deployments"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
  • 允许读取 pods 以及读写 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绑定从而限制针对某一个命名空间中定义的一个ConfigMap实例的访问):
rules:
- apiGroups: [""]
  resources: ["configmaps"]
  resourceNames: ["my-config"]
  verbs: ["get"]
  • 允许读取 core API Group 中的 nodes 资源(由于Node是集群级别资源,所以此ClusterRole定义需要与一个ClusterRoleBinding绑定才能有效):
rules:
- apiGroups: [""]
  resources: ["nodes"]
  verbs: ["get", "list", "watch"]
  • 允许对非资源 endpoint /healthz 及其所有子路径的 GET 和 POST 请求(此ClusterRole定义需要与一个ClusterRoleBinding绑定才能有效):
rules:
- nonResourceURLs: ["/healthz", "/healthz/*"] # 在非资源 URL 中,'*' 代表后缀通配符
  verbs: ["get", "post"]
  • 所有api 访问权限
rules:
- apiGroups: ["*"]
  resources: ["*"]
  verbs: ["*"]

角色绑定示例

  • 一个名为 alice@example.com 的用户:
subjects:
- kind: User
  name: "alice@example.com"
  apiGroup: rbac.authorization.k8s.io
展开阅读全文

本文系作者在时代Java发表,未经许可,不得转载。

如有侵权,请联系nowjava@qq.com删除。

编辑于

关注时代Java

关注时代Java