K8s记录-RBAC鉴权

概述

RBAC(Role-Based Access Control )基于角色的访问控制,这个基础概念不多赘述

在k8s中有四种对象用于支持该鉴权方式,Role,ClusterRole,RoleBinding,ClusterRoleBinding

分别对应为角色,集群角色,角色绑定关系,集群角色绑定关系

以上四种总体来说分为两类,角色定义,角色绑定

角色定义描述了角色具体的权限信息,而角色绑定则描述了角色和subject(如用户,用户组)的绑定关系

角色定义

Role

k8s中角色是和命名空间绑定的,该对象定义用户对于命名空间内的资源的权限,如pod,该命名空间下的serviceAccount等

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

ClusterRole

该对象定义的是集群作用域内的资源的权限,比如node,serviceAccount等

1
2
3
4
5
6
7
8
9
10
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
# "namespace" 被忽略,因为 ClusterRoles 不受名字空间限制
name: secret-reader
rules:
- apiGroups: [""]
# 在 HTTP 层面,用来访问 Secret 对象的资源的名称为 "secrets"
resources: ["secrets"]
verbs: ["get", "watch", "list"]

参数说明

  • apiGroups: 标识api组
  • resources:标识可以操作的资源
  • verbs:标识对资源的操作

apiGroups常用的"""extensions","apps"

常用的资源诸如:podsnodes等等

在 Kubernetes API 中,大多数资源都是使用对象名称的字符串表示来呈现与访问的。 例如,对于 Pod 应使用 “pods”。 RBAC 使用对应 API 端点的 URL 中呈现的名字来引用资源。 有一些 Kubernetes API 涉及 子资源(subresource),例如 Pod 的日志。 对 Pod 日志的请求看起来像这样:

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

在这里,pods 对应名字空间作用域的 Pod 资源,而 logpods 的子资源。 在 RBAC 角色表达子资源时,使用斜线(/)来分隔资源和子资源。 要允许某主体读取 pods 同时访问这些 Pod 的 log 子资源,你可以这么写

1
2
3
4
5
6
7
8
9
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"]

需要指定某个具体的资源可以这样写

1
2
3
4
5
6
7
8
9
10
11
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default
name: configmap-updater
rules:
- apiGroups: [""]
# 在 HTTP 层面,用来访问 ConfigMap 的资源的名称为 "configmaps"
resources: ["configmaps"]
resourceNames: ["my-configmap"]
verbs: ["update", "get"]

表示可以对名称为my-configmap的ConfigMap进行修改和获取的操作

verbs可能的值有

  • create
  • get
  • delete
  • list
  • update
  • edit
  • watch
  • exec

角色绑定

RoleBinding

角色绑定(Role Binding)是将角色中定义的权限赋予一个或者一组用户。 它包含若干 主体(用户、组或服务账户)的列表和对这些主体所获得的角色的引用。 RoleBinding 在指定的名字空间中执行授权,而 ClusterRoleBinding 在集群范围执行授权。

一个 RoleBinding 可以引用同一的名字空间中的任何 Role。 或者,一个 RoleBinding 可以引用某 ClusterRole 并将该 ClusterRole 绑定到 RoleBinding 所在的名字空间。 如果你希望将某 ClusterRole 绑定到集群中所有名字空间,你要使用 ClusterRoleBinding。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
apiVersion: rbac.authorization.k8s.io/v1
# 此角色绑定允许 "jane" 读取 "default" 名字空间中的 Pods
kind: RoleBinding
metadata:
name: read-pods
namespace: default
subjects:
# 你可以指定不止一个“subject(主体)”
- kind: User
name: jane # "name" 是区分大小写的
apiGroup: rbac.authorization.k8s.io
roleRef:
# "roleRef" 指定与某 Role 或 ClusterRole 的绑定关系
kind: Role # 此字段必须是 Role 或 ClusterRole
name: pod-reader # 此字段必须与你要绑定的 Role 或 ClusterRole 的名称匹配
apiGroup: rbac.authorization.k8s.io

ClusterRoleBinding

1
2
3
4
5
6
7
8
9
10
11
12
13
apiVersion: rbac.authorization.k8s.io/v1
# 此集群角色绑定允许 “manager” 组中的任何人访问任何名字空间中的 secrets
kind: ClusterRoleBinding
metadata:
name: read-secrets-global
subjects:
- kind: Group
name: manager # 'name' 是区分大小写的
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: secret-reader
apiGroup: rbac.authorization.k8s.io

参数说明

这里的subjects指的就是绑定的主体,kind可以是User,Group,ServiceAccount。name表示该对象的名称,apiGroup表示api组,一个角色定义可以绑定多个主体

一个比较完整的例子

创建ServiceAccount

1
2
3
4
5
6
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: test-server-account
namespace: test

赋予权限

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: test-role
namespace: test
rules:
- apiGroups: ["", "extensions", "apps"]
resources: ["*"]
verbs: ["*"]
- apiGroups: ["batch"]
resources:
- jobs
- cronjobs
verbs: ["*"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: test-rolebinding
namespace: test
subjects:
- kind: ServiceAccount
name: test-server-account
namespace: test
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: test-role
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: test-clusterrole
namespace: test
rules:
- apiGroups: [""]
resources: ["nodes","pods"]
verbs: ["list"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: test-clusterrolebinding
namespace: test
subjects:
- kind: ServiceAccount
name: test-server-account
namespace: test
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: test-clusterrole

在这个例子中我创建了一个Role名为test-role,具有对test命名空间的所有权限,一个ClusterRole名为test-clusterrole,对于集群里的nodes和pods只有查看的权限,然后把这两个权限都和ServiceAccount名称为test-server-account的用户进行绑定,所以test-server-account这个用户便有了上面两个角色所具有的权限,可以生成一下kubeconfig来测试一下权限

生成kubeconfig

可以使用下面的脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
server=$1
account=test-server-account
namespace=test
user=test-server-account
context_name=test-context
cluster_name=test-cluster

name=$(kubectl get sa/$account -n $namespace -o jsonpath='{.secrets[0].name}')
ca=$(kubectl get secret/$name -n $namespace -o jsonpath='{.data.ca\.crt}')
token=$(kubectl get secret/$name -n $namespace -o jsonpath='{.data.token}' | base64 --decode)

if [ ! -d "config" ];then
mkdir config
fi

echo "apiVersion: v1
kind: Config
clusters:
- name: $cluster_name
cluster:
certificate-authority-data: ${ca}
server: ${server}
contexts:
- name: $context_name
context:
cluster: $cluster_name
user: $user
current-context: $context_name
users:
- name: $user
user:
token: ${token}
" > config/test.kubeconfig


会在当前目录下创建一个config文件,这里需要传入k8s的master的apiservice的地址,

可以使用kubectl cluster-info查看,也可以查看~/.kube/config文件(注:如果使用rancher的rke,使用另外一个context的地址)

这里我脚本保存在generate.sh中,master的地址为https://172.17.5.6:6443

执行命令

1
sh generate.sh https://172.17.5.6:6443

使用

1
kubectl get sa --kubeconfig config/test.kubeconfig

会提示Error from server (Forbidden): serviceaccounts is forbidden....

1
kubectl get node --kubeconfig config/test.kubeconfig

而执行会返回节点列表

原理

k8s中创建了ServiceAccount之后会生成一个Secret用于鉴权,可以使用

1
kubectl get sa/test-server-account -o yaml

查看该ServiceAccount对应的Secret的名称

根据这个名称去获取对应Secret的访问token和ca信息,然后将这些信息按照kubeconfig文件的格式输出到文件,这种认证方式基于Service Account Tokens来认证的

参考:

https://kubernetes.io/zh/docs/reference/access-authn-authz/rbac/

https://www.cnblogs.com/zjz20/p/13182839.html

文章作者: C.c
文章链接: https://liquidcat.cc/K8s记录-RBAC鉴权.html
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Me