使用 RBAC签权
文章目录
- [使用 RBAC签权](#使用 RBAC签权)
一、RBAC介绍
1.1、介绍
基于角色(Role)的访问控制(RBAC)是一种基于组织中用户的角色来调节控制对计算机或网络资源的访问的方法。
RBAC签权机制使用rbac.authorization.k8s.io
API(Kubernetes API中的一组相关路径)组来驱动签权决定,允许你通过Kubernetes API动态配置策略。
1.2、RBAC四种对象
RBAC API声明了四种 Kubernetes 对象:Role、ClusterRole、RoleBinding和ClusterRoleBinding 。你可以像使用其他 Kubernetes 对象一样,通过类似kubectl
这类工具描述或修补 RBAC 对象
- 注意*:这些对象在设计即实施了一些访问限制。如果你在学习过程中对集群做了更改,请避免特权提升
二、Role和ClusterRole
RBAC的Role 或ClusterRole中包含一组代表相关权限的规则。这些权限是纯碎累加的(不存在拒绝某些操作的规则)。
Role总是用来在某个名称空间内设置访问权限;在你创建Role时,你必须指定该Role所属的名称空间。
与之相对,ClustreRole则是一个集群作用域的资源。这两种资源的名称不同(Role和ClusterRole)是因为 Kubernetes 对象要么是名称空间作用域的,要么是集群作用域,不可两者兼具。
ClusterRole 若干用法。你可以用它来:
- (1)、定义对某名称空间域对象的访问权限,并将名称空间内被授予访问权限;
- (2)、名称空间作用域的对象设置访问权限,并将授予跨所有名称空间的访问权限;
- (3)、为集群作用域的资源定义访问权限。
如果你希望在名称空间内角色,应该使用Role;如果你希望定义集群范围的角色,应该使用ClusterRole。
三、RoleBinding和ClusterRoleBinding
角色绑定(Role Binding)是将角色中定义的权限赋予一个或者一组用户。它包含若干主体(Subject) (用户、组或服务账户)的列表和对这些主体所获得的角色的引用。RoleBinding在指定的名称空间中执行授权,而ClusterRoleBinding在集群范围执行授权。
一个RoleBinding可以引用同一的名称空间中的任何Role。或者,一个RoleBinding可以引用某ClusterRole并将该ClusterRole绑定到RoleBinding所在的名称空间。如果你希望将某ClusterRole绑定到集群中所有名称空间,你要是用ClusterRoleBinding。
RoleBindimg或ClusterRoleBinding对象的名称必须是合法的路径分段名称
四、示例Role
4.1、创建Kubernetes用户
- 创建 Kubernetes 的wzh1账号
bash
# 进去 Kubernetes 的公钥设施文件夹
[root@master ~]# cd /etc/kubernetes/pki/
# 生成 wzh 认证证书
[root@master pki]# openssl genrsa -out wzh1.key 2048
[root@master pki]# openssl req -new -key wzh1.key -out wzh1.csr -subj "/CN=wzh1"
[root@master pki]# openssl x509 -req -in wzh1.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out wzh1.crt -days 3650
# 将 wzh1 账户加入Kubernetes
[root@master pki]# kubectl config set-credentials wzh1 --client-certificate=./wzh1.crt --client-key=./wzh1.key --embed-certs=true
[root@master pki]# kubectl config set-context wzh1@kubernetes --cluster=kubernetes --user=wzh1
bash
# 查看 Kubernetes Config
[root@master pki]# kubectl config view
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: DATA+OMITTED
server: https://192.168.93.145:6443
name: kubernetes
contexts:
- context:
cluster: kubernetes
user: kubernetes-admin
name: kubernetes-admin@kubernetes
#####################################################
- context:
cluster: kubernetes
user: wzh1
name: wzh1@kubernetes
#####################################################
current-context: kubernetes-admin@kubernetes
kind: Config
preferences: {}
users:
- name: kubernetes-admin
user:
client-certificate-data: REDACTED
client-key-data: REDACTED
- name: wzh1
user:
client-certificate-data: REDACTED
client-key-data: REDACTED
4.2、Role示例
- 下面是一个位于
default
名称空间的Role的示例,可以用来授予对Pod的读访问权限:
bash
[root@master rbac]# cat role.yaml
apiVersion: "rbac.authorization.k8s.io/v1"
kind: Role # 创建的资源类型
metadata:
namespace: default # 这个Role将使用与default名称空间中
name: pod-reader
rules: # 规则
- apiGroups: [""] # "" 标明核心组 core API(不用纠结什么意思)
resources: ["pods"] # 指定权限使用的资源类型为Pod,适用的资源要写全称,可以通过kubectl api-resources 查看NAME字段,就是资源的全称
verbs: ["get","watch","list"] # 指定可以对指定资源执行的操作
bash
# 加载资源
[root@master rbac]# kubectl apply -f role.yaml
role.rbac.authorization.k8s.io/pod-reader created
bash
# 查看 Role 角色创建情况
[root@master rbac]# kubectl get role pod-reader
NAME CREATED AT
pod-reader 2024-08-19T00:54:42Z
4.3、RoleBinding
- 下面的例子中的 RoleBinding将"pod-reader" Role授予在"default"名称空间中的用户"wzh1".这样,用户"wzh1"就具有了读取"default"名称空间中所有Pod的权限。
bash
[root@master rbac]# cat rolebinding.yaml
apiVersion: "rbac.authorization.k8s.io/v1"
# 此角色绑定运行 "wzh1" 用户读取 "default" 名称空间中的Pod
# 你需要在该名称空间中又有一个名为"pod-reader"的 Role
kind: RoleBinding # 创建的类型
metadata:
name: read-pods
namespace: default # 与Role保持同一名称空间即可
subjects:
# 你可以指定不止一个"subject(主体)"
- kind: User # 创建的是用户类型(User)
name: wzh1 # 需要绑定的用户
apiGroup: rbac.authorization.k8s.io # 不用纠结这个字段
roleRef: # 指定与某Role 或 ClusterRole的绑定关系
kind: Role # 此字段必须是Role 或 ClusterRole
name: pod-reader # 此字段必须要与你绑定的Role 或 ClusterRole的名称匹配
apiGroup: rbac.authorization.k8s.io
bash
# 加载资源
[root@master rbac]# kubectl apply -f rolebinding.yaml
rolebinding.rbac.authorization.k8s.io/read-pods created
4.4、验证
bash
# 切换到Kubernetes的wzh1用户
[root@master rbac]# kubectl config use-context wzh1@kubernetes
Switched to context "wzh1@kubernetes".
bash
# 查看 default 中的Pod
# 通过以下可以看出,是可以访问 default 名称空间中的 Pod 的,只是该名称空间下没有Pod
[root@master rbac]# kubectl get pod -n default
No resources found in default namespace.
bash
# 做一些没有赋予权限的操作将会报错,比如使用wzh1用户查看默认名称空间service资源
[root@master rbac]# kubectl get service -n default
Error from server (Forbidden): services is forbidden: User "wzh1" cannot list resource "services" in API group "" in the namespace "default"
4.5、退回管理员权限用户
bash
[root@master rbac]# kubectl config use-context kubernetes-admin@kubernetes
Switched to context "kubernetes-admin@kubernetes".
五、示例ClusterRole
- ClusterRole同样可以用于授予Role能够授予的权限。因为ClusterRole属于集群范围,所以它可以为以下资源授予访问权限:
- 集群范围资源(比如节点(Node))
- 非资源端点(比如/healthz)
- 跨名称空间访问的名称空间作用域的资源(如Pod)
- 比如,你可以使用ClusterRole来允许某特定用户指定
kubectl get pod -A
- 比如,你可以使用ClusterRole来允许某特定用户指定
5.2、创建Kubernetes用户
- 创建 Kubernetes 的wzh2账号
bash
# 进去 Kubernetes 的公钥设施文件夹
[root@master ~]# cd /etc/kubernetes/pki/
# 生成 wzh2 认证证书
[root@master pki]# openssl genrsa -out wzh2.key 2048
[root@master pki]# openssl req -new -key wzh2.key -out wzh2.csr -subj "/CN=wzh2"
[root@master pki]# openssl x509 -req -in wzh2.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out wzh2.crt -days 3650
# 将 wzh 账户加入Kubernetes
[root@master pki]# kubectl config set-credentials wzh2 --client-certificate=./wzh2.crt --client-key=./wzh2.key --embed-certs=true
[root@master pki]# kubectl config set-context wzh2@kubernetes --cluster=kubernetes --user=wzh2
bash
# 查看 Kubernetes Config
[root@master pki]# kubectl config view
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: DATA+OMITTED
server: https://192.168.93.145:6443
name: kubernetes
contexts:
- context:
cluster: kubernetes
user: kubernetes-admin
name: kubernetes-admin@kubernetes
- context:
cluster: kubernetes
user: wzh1
name: wzh1@kubernetes
#####################################################
- context:
cluster: kubernetes
user: wzh2
name: wzh2@kubernetes
#####################################################
current-context: kubernetes-admin@kubernetes
kind: Config
preferences: {}
users:
- name: kubernetes-admin
user:
client-certificate-data: REDACTED
client-key-data: REDACTED
- name: wzh1
user:
client-certificate-data: REDACTED
client-key-data: REDACTED
- name: wzh2
user:
client-certificate-data: REDACTED
client-key-data: REDACTED
5.3、ClusterRole示例
- 下面是一个ClusterRole的示例,可用来为任意一特定名称空间中的Secret授予读访问权限,或者跨名称空间的访问权限(取决于该角色是如何绑定的):
bash
[root@master pki]# cat clusterrole.yaml
apiVersion: "rbac.authorization.k8s.io/v1"
kind: ClusterRole # 创建的资源类型
metadata:
# "namespace" 被忽略,因为 ClusterRole 不受名称空间限制
name: secret-reader
rules: # 规则
- apiGroups: [""] # 核心组,不用纠结这个字段
# 在 HTTP 层面,用来访问 Secret 资源的名称为 "secrets"
resources: ["secrets"] # 可以操作的资源对象
verbs: ["get","watch","list"] # 可以做使用kubectl对secret做的操作
bash
# 加载资源
[root@master pki]# kubectl apply -f clusterrole.yaml
clusterrole.rbac.authorization.k8s.io/secret-reader created
bash
# 查看 ClusterRole 角色创建情况
[root@master pki]# kubectl get clusterrole secret-reader
NAME CREATED AT
secret-reader 2024-08-19T01:31:49Z
5.3、ClusterRoleBinding
- 要跨整个集群访问全新啊的授予,你可以使用一个ClusterRoleBinding。下面的ClusterRoleBinding允许"wzh2"用户访问任何名称空间中的Secret。
bash
[root@master pki]# cat clusterrolebinding.yaml
apiVersion: "rbac.authorization.k8s.io/v1"
# 此集群角色绑定允许 "wzh2"用户访问任何名称空间中的Secret资源
kind: ClusterRoleBinding
metadata:
name: read-secrets-global
subjects:
- kind: User # 用户类型为(User)
name: wzh2 # 此允许必须存在
apiGroup: rbac.authorization.k8s.io
roleRef: # 指定引用的角色资源
kind: ClusterRole
name: secret-reader
apiGroup: rbac.authorization.k8s.io
bash
# 加载资源
[root@master pki]# kubectl apply -f clusterrolebinding.yaml
clusterrolebinding.rbac.authorization.k8s.io/read-secrets-global created
5.4、验证
bash
# 切换到Kubernetes的wzh2用户
[root@master pki]# kubectl config use-context wzh2@kubernetes
Switched to context "wzh2@kubernetes".
bash
# 查看ClusterRole角色中运行查看的资源
# ClusterRole 针对的是全局的的权限,也就是集群,可以看到集群所有Secret资源
[root@master pki]# kubectl get secret -A
NAMESPACE NAME TYPE DATA AGE
default default-token-9vp59 kubernetes.io/service-account-token 3 19d
kube-flannel default-token-x4r9d kubernetes.io/service-account-token 3 19d
kube-flannel flannel-token-kjfjp kubernetes.io/service-account-token 3 19d
kube-node-lease default-token-nwgqw kubernetes.io/service-account-token 3 19d
...
bash
# 查看别的资源将会报错
[root@master pki]# kubectl get pod -A
Error from server (Forbidden): pods is forbidden: User "wzh2" cannot list resource "pods" in API group "" at the cluster scope
六、删除资源的要求
- 创建绑定之后,你不能再修改绑定对象所引用的Role或ClusterRole。试图改变绑定对象的
roleRef
将导致合法性检查错误。如果你想要改变现有绑定对象中的roleRef
字段的内容,必须删除重新创建绑定对象
七、扩展1
7.1、对资源的引用
- 在Kubernetes API中,大多数资源都是使用对象名称的资源串表示来呈现与访问的。例如,对于Pod应用使用"Pods"。RBAC使用对应的API端点的URL中呈现的名称来引用资源。有一些Kubernetes API涉及子资源(subresource),例如Pod的日志。对于Pod的日志请求看起来像这样:
bash
GET /api/v1/namespaces/{namespace}/pods/{name}/log
- 在这里,
Pods
对应的名称空间作用域的Pod资源,而log
是pogs
的子资源。在RBAC角色表达子资源时,使用斜线(/
)来分隔资源和子资源。要么允许某主体读取pods
同时访问这些Pod的log
子资源,你可以这样写:
bash
# 你可以把以上的所有资源删除,来进行以下的验证
[root@master rbac]# cat role.yaml
apiVersion: "rbac.authorization.k8s.io/v1"
kind: Role
metadata:
namespace: default
name: pod-reader
rules:
- apiGroups: [""]
resources: ["pods","pods/log"]
verbs: ["get","watch","list"]
# 最终可以实现以下效果
[root@master rbac]# kubectl logs nginx
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
- 对于某些请求,也可以通过
resourceNames
列表按名称引用资源。在指定时,可以将请求限定为资源的单个实例。下面的例子中限制可以get
和update
一个名为my-configmap1
的Config Map。
bash
# 创建两个ConfingMap
[root@master rbac]# kubectl create configmap my-configmap1
[root@master rbac]# kubectl create configmap my-configmap2
bash
[root@master rbac]# cat role.yaml
apiVersion: "rbac.authorization.k8s.io/v1"
kind: Role
metadata:
namespace: default
name: pod-reader
rules:
- apiGroups: [""]
resources: ["configmaps"]
resourceNames: ["my-configmap1"] # 只能在defalut名称空间中查看名为my-configmaop1的ConfigMap
verbs: ["get","watch","list"]
bash
# 进行RoleBinding之后可以实现以下效果
# 有权限可以查看 my-configmap1
[root@master rbac]# kubectl get configmap my-configmap1
NAME DATA AGE
my-configmap1 0 2m1s
# 没有权限查看 my-configmap2
[root@master rbac]# kubectl get configmap my-configmap2
Error from server (Forbidden): configmaps "my-configmap2" is forbidden: User "wzh1" cannot get resource "configmaps" in API group "" in the namespace "default"
八、扩展2
8.1、RoleBinding也可以引用ClusterRole,
-
以将对应ClusterRole中定义的访问权限授予RoleBind所在的名称空间的资源。这种引用是的你跨整个集群定义一组通用的角色,之后在多个名称空间中复用即可。
-
例如:尽管下面的RoleBinding引用的是一个ClusterRole,"wzh1"(这里的主体,(User用户))只能访问"development"名称空间中的Secret对象,因为RoleBinding所在的名称空间(由其metadata决定)是"developemtn"。
bash
# 创建 ClusterRole角色
[root@master rbac]# cat clusterrole.yaml
apiVersion: "rbac.authorization.k8s.io/v1"
kind: ClusterRole # 创建的资源类型
metadata:
# "namespace" 被忽略,因为 ClusterRole 不受名称空间限制
name: secret-reader
rules: # 规则
- apiGroups: [""] # 核心组,不用纠结这个字段
# 在 HTTP 层面,用来访问 Secret 资源的名称为 "secrets"
resources: ["secrets"] # 可以操作的资源对象
verbs: ["get","watch","list"] # 可以做使用kubectl对secret做的操作
bash
# 创建 RoleBinding
[root@master rbac]# cat rolebinding.yaml
apiVersion: "rbac.authorization.k8s.io/v1"
# 此角色绑定运行 "wzh1" 用户读取 "development" 名称空间中的Secret
# 你需要在该名称空间中又有一个名为"secret-reader"的 ClusterRole
kind: RoleBinding # 创建的类型
metadata:
name: read-secrets
namespace: development # RoleBinding的名称空间决定了访问权限的授予范围
subjects:
# 你可以指定不止一个"subject(主体)"
- kind: User # 创建的是用户类型(User)
name: wzh1 # 需要绑定的用户
apiGroup: rbac.authorization.k8s.io # 不用纠结这个字段
roleRef: # 指定与某Role 或 ClusterRole的绑定关系
kind: ClusterRole # 此字段必须是Role 或 ClusterRole
name: secret-reader # 此字段必须要与你绑定的Role 或 ClusterRole的名称匹配
apiGroup: rbac.authorization.k8s.io
bash
# 创建所需名称空间
[root@master rbac]# kubectl create namespace development
namespace/development created
# 加载资源
[root@master rbac]# kubectl apply -f clusterrole.yaml
[root@master rbac]# kubectl apply -f rolebinding.yaml
bash
# 验证
# 切换 wzh1 用户
[root@master rbac]# kubectl config use-context wzh1@kubernetes
[root@master rbac]# kubectl get secrets -n development
NAME TYPE DATA AGE
default-token-sq4t8 kubernetes.io/service-account-token 3 106s
# 查看别的名称空间中的secret就会报错没有权限
[root@master rbac]# kubectl get secrets -n default
Error from server (Forbidden): secrets is forbidden: User "wzh1" cannot list resource "secrets" in API group "" in the namespace "default"