一文读懂k8s RBAC权限控制
内容概览
k8s API服务器在接收到请求后,会经过 1) 认证插件; 如果其中一个认证插件通过,则认证结束。2) 进入授权流程。3) 进入准入控制链imToken官网下载,所有注册的注入控制节点全部通过,则准入结束
如下图
上面流程中:认证插件将返回通过认证的用户/用户组;然后将其交给授权信息检查用户/用户组是否有权限执行某个操作。RBAC授权逻辑通过将用户与角色绑定来决定是否可以执行某项操作。主体(User/)与角色关联,角色与资源权限关联。
如下图
下面来逐一看下各节点,我们按照 1) 用户 2) 角色 3) 绑定 的顺序来看
RBAC鉴权流程用户 and 用户组
- 真实用户User (k8s不维护相关资源类型,用户和所属用户组全部由外部系统管控)
- 访问k8s的服务 (k8s可创建并维护)
(其中默认也是一种用户。作为User使用时名称为 ::,所属用户组为 :: )
创建类型的用户示例
apiVersion: v1
kind: ServiceAccount
metadata:
name: custom
复制
此时,基础组件里的token-自动(根据-----key-file的证书)为生成 ,中包含的token信息,即可用作http token请求中的认证信息。获取方式如下:
# 获取secrets名称
[root ~/custom]# kubectl get serviceaccount custom-job -o jsonpath={.secrets[0].name}
# 获取token
[root ~/custom]# kubectl get secret -o jsonpath={.data.token}|base64 -d
复制
结尾会有示例代码
Role 和
apiVersion: rbac.authorization.k8s.io/v1
kind: Role # ClusterRole这里需要改
metadata:
name: custom
namespace: default # ClusterRole 无namespace限制
rules:
- apiGroups:
- batch # jobs 所在apiGroups
- ""
resources:
- jobs
- configmaps
verbs:
- get
- list
复制
Role 与 最大区别在于:Role有区分,如果要应用在多个nstoken 权限管理·(中国)官方网站,需要每个ns下创建一个Role 或者 选择
中列出的所有资源 所属的 必须填写。查看方式
[root@ ~/custom]# kubectl api-resources | head -1; kubectl api-resources | grep job
NAME SHORTNAMES APIGROUP NAMESPACED KIND
cronjobs cj batch true CronJob
jobs batch true Job
复制
结果中 jobs 所在为batch。核心资源所属为 "",这个需要声明在列表里。
和
有了角色 和 用户,现在只需要绑定,就可以让用户拥有角色权限。
以 为例,来看下 User 和 两种绑定方式
# User类型绑定
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: custom
namespace: default
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: custom
subjects:
- kind: User
name: system:serviceaccount:custom
namespace: default
# ServiceAccount类型绑定
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: custom
namespace: default
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: custom
subjects:
- kind: ServiceAccount
name: custom-job
namespace: default
复制
如上,`` 为引用的规则, `` 为赋予角色的主体(用户或)。
的 kind 为主体类型,包含: Group、User、 三种。
的 kind 为 Group 时,name 字段有一批内置的字段,抄录如下
sujects:
- kind: Group
name: system:serviceaccounts:qa # 为qa命名空间中所有serviceaccount授权
apiGroup: rbac.authorization.k8s.io
name: system:sesrviceaccounts # 为所有命名空间的serviceaccount授权
name: system:authenticated # 为所有已认证用户授权
name: system:unauthenticated # 为所有未认证用户授权
复制
上述,一个有权限的账号创建完成。由于Role和都在下创建,所以只能访问命名空间下的资源(仅限Role中配置的资源和)。我们测试一下:
访问 k8s 服务
访问k8s资源方式
# python3 环境 首先安装 kubernetes(18.20.0)包
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from kubernetes.client import api_client
from kubernetes.client.api import core_v1_api
from kubernetes import client
ApiToken = ""
configuration = client.Configuration()
configuration.host = "https://:"
configuration.verify_ssl = False
configuration.api_key = {"authorization": "Bearer " + ApiToken}
client1 = api_client.ApiClient(configuration=configuration)
api = core_v1_api.CoreV1Api(client1)
#ret = api.list_namespaced_pod(async_req=True) # 报错
ret = api.list_namespaced_config_map(namespace="default", async_req=True)
result = ret.get()
print(result)
复制
代码运行后将打印 下的所有信息。 如果执行注释内容,则返回:
kubernetes.client.exceptions.ApiException: (403)
Reason: Forbidden
HTTP response headers: HTTPHeaderDict({'Content-Type': 'application/json', 'X-Content-Type-Options': 'nosniff', 'Date': 'Wed, 27 Oct 2021 11:18:46 GMT', 'Content-Length': '289'})
HTTP response body: {"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"pods is forbidden: User \"system:serviceaccount:default:custom\" cannot list resource \"pods\" in API group \"\" in the namespace \"kube-system\"","reason":"Forbidden","details":{"kind":"pods"},"code":403}
复制
内置的权限环境
来看下为什么时,我们为什么可以查看集群所有资源
# 查看kubectl上下文配置
[root@ ~/custom]# kubectl config view
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: DATA+OMITTED
server: https://9.215.152.23:60002
name: local
contexts:- context:
cluster: local
user: admin
name: master
current-context: master
kind: Config
preferences: {}
users:
- name: admin
user:
token: ***
复制
contexts 是所有用户上下文,current-context是当前使用上下文,对应用户admin
用户与角色绑定关系在名为admin的ClusterRoleBinding中
复制
[root@ ~/custom]# kubectl get clusterrolebinding admin -n kube-system -o yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
...
name: admin
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: admin
namespace: kube-system
复制
看下这个角色
[root@ ~/custom]# kubectl get ClusterRole -n kube-system cluster-admin -o yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
...
name: cluster-admin
rules:
- apiGroups:
- '*'
resources:
- '*'
verbs:
- '*'
- nonResourceURLs:
- '*'
verbs:
- '*'
复制
再看下为什么pod内默认也可以访问当前ns下的信息
复制
随意打开一个未挂载serviceAccount的pod,可以发现一些volume信息
复制
# containers信息
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-z2gm7 (ro)
...
# pod信息
Volumes:
default-token-z2gm7:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-z2gm7
Optional: false
复制
如上,有名为 `-token-z2gm7` 的 被挂载到容器的 `/var/run//.io/` 下。 根据名称规律,我们在命名空间下找到 `` 的
[root@ ~]# kubectl describe sa default -n enqtest
Name: default
Namespace: test
Labels:
Annotations:
Image pull secrets:
Mountable secrets: default-token-z2gm7
Tokens: default-token-z2gm7
复制
进入容器查看这个目录:
[root@test /run/secrets/kubernetes.io/serviceaccount]# ll
lrwxrwxrwx 1 root root 13 7月 20 13:14 ca.crt -> ..data/ca.crt
lrwxrwxrwx 1 root root 16 7月 20 13:14 namespace -> ..data/namespace
lrwxrwxrwx 1 root root 12 7月 20 13:14 token -> ..data/token
复制
捋一下流程:
1) 用户创建ns
2) 监听到NS创建,为其生成 名称的
3) Token 监听到SA创建,会用 API私钥(kube-组件的 -----key-file) 创建一个token,并用此token、API 的CA证书(用来检测服务器返回的准确性)、和命名空间信息,打包为一个对象,放在 里
4) 创建未声明的pod,准入控制插件()检测到,修改pod挂载信息注入
访问样例
复制
[root@ ~]# curl -H "Authorization: Bearer $TOKEN" https://:443 -k
复制
另一个类型 User 创建流程好像是自己用证书创建,最终展现在k8s环境就是context, 后续再填坑。
债见
复制
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。