文章目录
- 概要
- Kubernetes API
- 了解 Kubernetes 中的 RBAC
- Roles and Role Bindings:
- ClusterRoles and ClusterRoleBindings
- 检查访问权限:
- 外部用户
- 结论
概要
Kubernetes 是容器化应用的强大引擎,但仅仅关注部署和扩展远远不够,集群的安全同样至关重要。这时,角色权限控制(Role-Based Access Control,RBAC)就派上了用场。本文将深入了解 Kubernetes RBAC,帮助您构建精细化的安全策略,并通过实例详细展示其工作原理。
Kubernetes API
在介绍 RBAC 之前,需要明确授权模型在整个架构中的位置。
以下是向 Kubernetes 集群提交一个 Pod 的示例:
cat <<EOF |kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: nginx
namespace: web
spec:
serviceAccountName: john
containers:
- image: nginx
name: nginx
ports:
- containerPort: 8080
EOF
部署Pod 到集群:
kubectl apply -f pod.yaml
运行 kubectl apply 时,会依次执行以下步骤:
- 从 KUBECONFIG 文件中读取配置信息。
- 查询 API 以发现可用的 API 和对象。
- 在客户端验证资源,检查是否存在明显错误。
- 将包含资源定义的请求发送到 kube-apiserver。
当 kube-apiserver 接收到请求时,不会立即将其存储到 etcd 中。
首先,会对请求的合法性进行验证,即对请求进行身份认证。
通过身份认证后,还会检查请求是否具备创建资源的权限。
身份和权限是两个独立的概念。
即使拥有集群访问权限,也不一定能够创建或读取所有资源。
授权通常通过基于角色的访问控制(RBAC)实现。
RBAC 提供细粒度的权限控制,用于限制用户或应用程序的操作范围。
从实际操作的角度来看,API 服务器按以下顺序执行操作:
- A. 验证用户身份
如果身份验证失败,返回 401 Unauthorized 并拒绝请求。
如果身份验证通过,进入下一阶段。 - B. 检查用户权限
如果用户无权访问资源,返回 403 Forbidden 并拒绝请求。
如果用户具备权限,继续处理请求。
通过 RBAC 角色实现用户与权限的解耦
RBAC 是一种基于组织中用户角色分配资源访问权限的模型。
为更直观地理解其工作原理,可以设想从零设计一个授权系统。
要确保用户对特定资源具有写入权限,可以采用一种简单的实现方式,即创建一个包含三列的列表,例如:
| User | Permission | Resource |
| ------ | ---------- | -------- |
| John | read+write | app1 |
| Emily | read | app2 |
| Michael| read | app2 |
在此示例中:
John 拥有对 app1 的读写权限,但无法访问 app2。
Emily 和 Michael对 app2 仅拥有读取权限,但无法访问 app1。
当用户和资源数量较少时,这种表格形式可以正常使用,但随着规模扩大,可能会显现一些局限性。
例如,如果将 Michael和 Emily 归为同一团队,并授予其对 app1 的读取权限,表中将需要新增以下条目:
| User | Permission | Resource |
| ------ | ---------- | ---------- |
| John | read+write | app1 |
| Emily | read | app2 |
| Michael| read | app2 |
| Emily | read | app1 |
| Michael| read | app1 |
这种设计难以直接体现 Emily和 Michael因同属一个团队而拥有相同访问权限的关系。
可以通过在表中添加“Team”列来解决此问题,但更优的方式是拆分这些关系:
- 定义一个通用的权限容器,即角色(Role)。
- 不直接将权限分配给用户,而是将权限包含在反映其在组织中角色的角色中。
- 最后,将角色与用户关联起来。
可以通过以下方式进行改进:
- 不再使用单一表格,而是将结构拆分为两个表格:
- 第一个表格将权限映射到角色。
- 第二个表格将角色与身份关联起来。
| Role | Permission | Resource |
| ------ | ---------- | ---------- |
|admin | read+write | app1 |
|viewer | read | app2 |
| User | Role |
| ------ | ----------|
|John | admin |
|Emily | viewer |
|Michael | viewer |
当需要将 Mo 设置为 app1 的管理员时,可以通过以下方式将角色分配给用户:
| User | Role |
| ------ | ----------------|
|John | admin |
|Emily | reviewer |
|Michael | viewer,admin |
通过使用角色将用户与权限解耦,可以简化大型组织中涉及众多用户和权限的安全管理。
了解 Kubernetes 中的 RBAC
Kubernetes (K8s) 中的 RBAC(基于角色的访问控制)是一种安全机制,用于定义和实施对集群中各类资源的细粒度访问控制策略,是管理和保护 Kubernetes API 服务器及集群资源访问的重要组成部分。
RBAC 通过定义角色(Role)和角色绑定(Role Binding),用于指定对特定 Kubernetes 资源(如 Pod、Service、ConfigMap)及命名空间级别允许执行的action(verbs)。以下是 RBAC 的一些核心概念:
- 角色(Roles):角色是定义在特定命名空间内,允许对某个资源执行的操作集合。例如,可以创建一个角色,允许在特定命名空间中对 Pod 执行读取和列出操作。
- 角色绑定(Role Bindings):角色绑定将角色与一个或多个用户、组或服务账户关联,指定哪些主体可以执行角色中定义的操作。例如,可以将角色绑定到特定用户或用户组。
- 集群角色(ClusterRoles):与角色仅限于单一命名空间不同,集群角色不受命名空间限制。集群角色定义了对集群级资源(如节点或持久卷)执行的操作。
- 集群角色绑定(ClusterRoleBindings):集群角色绑定将集群角色与用户、组或服务账户关联,类似于角色绑定。它们确定哪些主体可以访问所有命名空间中的集群级资源。
通过使用 RBAC,可以创建一个细粒度的访问控制系统,符合组织的安全需求。这确保了用户、应用程序和服务拥有执行任务所需的适当访问权限,同时保持 Kubernetes 集群的整体安全。
基于角色的访问控制(Role-Based Access Control)是防止未经授权访问的保护屏障!这种安全机制可以为 Kubernetes 资源创建高度精细的访问策略。通过它,可以为用户、应用程序和服务分配恰到好处的权限,同时确保集群的安全性不受威胁。
Roles and Role Bindings:
角色(Roles)用于为命名空间中的特定资源定义访问策略。角色绑定(Role Bindings)将角色与用户、用户组或服务账户关联,明确访问权限的分配关系。
示例:
1.首先创建一个service account
cat <<EOF|kubectl apply -f -
apiVersion: v1
kind: ServiceAccount
metadata:
name: john
namespace: web
EOF
2.定义一个名为“pod-reader-role”的角色。
cat <<EOF |kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: web
name: pod-reader-role
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list"]
说明:
此 YAML 文件定义了一个名为 “pod-reader-role” 的角色,适用于 “web” 命名空间,授权对 “pods” 执行 “get” 和 “list” 操作。
3.定义一个名为“pod-reader-role-binding”的角色绑定,并将其绑定到“web”命名空间中的服务用户“john”。
cat <<EOF |kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: pod-reader-role-binding
namespace: web
subjects:
- kind: ServiceAccount
name: john
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: pod-reader-role
apiGroup: rbac.authorization.k8s.io
EOF
说明:
该 YAML 文件创建了一个名为 “pod-reader-role-binding” 的角色绑定(Role Binding),将 “pod-reader-role” 角色与 “web” 命名空间中的用户 “john” 关联起来。用户 “john” 现在拥有了 “pod-reader-role” 的权限。
ClusterRoles and ClusterRoleBindings
集群角色(ClusterRoles)和集群角色绑定(ClusterRoleBindings)将 RBAC 扩展至整个集群,允许对集群级资源的访问权限进行管理。
1.定义一个名为“node-reader-cluster-role”的clusterrole
cat <<EOF |kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: node-reader-cluster-role
rules:
- apiGroups: [""]
resources: ["nodes"]
verbs: ["get", "list"]
EOF
说明:
ClusterRole 定义了集群范围内的权限,用于控制对 Kubernetes 集群中资源的访问。上面的 YAML 文件定义了一个名为 “node-reader-cluster-role” 的 ClusterRole,允许对 “nodes” 资源执行 “get” 和 “list” 操作,用于读取节点信息。
2.定义一个名为“node-reader-cluster-binding”的集群角色绑定,并将其绑定到服务用户“admin”。
cat <<EOF |kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: node-reader-cluster-binding
subjects:
- kind: ServiceAccount
name: admin
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: node-reader-cluster-role
apiGroup: rbac.authorization.k8s.io
EOF
说明:
在这个 YAML 文件中,名为“node-reader-cluster-binding”的集群角色绑定将“node-reader-cluster-role”集群角色与集群级的用户“admin”关联起来。通过这个绑定,用户“admin”获得了“node-reader-cluster-role”集群角色中定义的权限,从而能够在整个集群中管理节点。
检查访问权限:
配置 RBAC 后,可通过 kubectl auth can-i 命令验证权限,确保角色具备所需的操作权限。
示例:
- 验证 “john” 是否有权限在 “webapp” 命名空间中列出 pods
$ kubectl auth can-i list pods --as=system:serviceaccount:web:john -n web
yes
2.执行list pods验证
$ kubectl exec -it -n web nginx -- bash
$ curl -k -s -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" https://kubernetes.default.svc/api/v1/namespaces/web/pods|jq '.items[].metadata.name'
"my-pod"
"nginx"
"redis-77598f9f86-g4dqg"
"redis-77598f9f86-hpmsh"
"service-python-7f7c9d4fc4-jhp4d"
"webserver-5f9579b5b5-4vj77"
"webserver-5f9579b5b5-qw2m4"
外部用户
1.创建user
在 Kubernetes 中,User 和 ServiceAccount 是独立的概念。一个 User 通常由外部身份管理系统(如 LDAP、OIDC)认证,而 ServiceAccount 是 Kubernetes 内置的一种资源,用于为应用程序或 Pod 提供身份。它们没有直接的关联机制,但可以通过为 User 和 ServiceAccount 配置相同的 RoleBinding 或 ClusterRoleBinding,让它们具有相同的权限,从而达到“关联”目的。
cat <<EOF |kubectl apply -f -
> apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: shared-access-binding
namespace: web
subjects:
- kind: User
name: john # External user
apiGroup: rbac.authorization.k8s.io
- kind: ServiceAccount
name: john # ServiceAccount
namespace: web
roleRef:
kind: Role
name: pod-reader-role
apiGroup: rbac.authorization.k8s.io
> EOF
2.验证权限
$ kubectl auth can-i list pods --as=john -n web
yes
3.执行list pods验证
$ sa_john_token=$(kubectl create token john -n web)
$ echo $sa_john_token
eyJhbGciOiJSUzI1NiIsImtpZCI6ImxMVXQ2cTI1cnJFeWVEa0hpWW9SS2oxemRwUVBPWWY3Y0NPZDEtWXViajAifQ.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiXSwiZXhwIjoxNzM3NzA0NzUxLCJpYXQiOjE3Mzc3MDExNTEsImlzcyI6Imh0dHBzOi8va3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsIiwianRpIjoiZjhjYzY3ZWQtYWQ2Mi00OGQ5LTgyNDQtMjg5NDExYTEwODBiIiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJ3ZWIiLCJzZXJ2aWNlYWNjb3VudCI6eyJuYW1lIjoiam9obiIsInVpZCI6IjQxMWU5NzU5LTI0ZDItNDEyMy04MTNmLTEyNTdjYzhmNzE4ZCJ9fSwibmJmIjoxNzM3NzAxMTUxLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6d2ViOmpvaG4ifQ.PZPhGJ9djwI0DaTgHGqoQ0nrov2Cokw1WObL42H-TOcRE9SCAgHaxGgIkjAqgJYja5djmjk-SNneSoPD1jq9PTp2NaXBxCfLMHHCfe2QyN0eB3DiV7SFQ2IWZVBFYa6c8ufNFdm85oOPzmcXZDU-T59xpOR6OqgREWhSAQ4LRyFDC-TAqXf1YncKV2i2rItn1OlgNENdqwD2dBYVM9CZvlCt5za7ZwfYcUve1DD9_rZK0VC1Jnc_I8zf8M7mOrucAiZOLXcaFBfFNMPIWa1t1k2EWbnkt8kLFmDkESJ2S1oMHdbpKPZzspFGAtJDMKMHa9W1T3A92kPz_uSGPkRgVg
$ curl -k -s -H "Authorization: Bearer $sa_john_token" https://172.19.6.5:6443/api/v1/namespaces/web/pods | jq '.items[].metadata.name'
"my-pod"
"nginx"
"redis-77598f9f86-g4dqg"
"redis-77598f9f86-hpmsh"
"service-python-7f7c9d4fc4-jhp4d"
"webserver-5f9579b5b5-4vj77"
"webserver-5f9579b5b5-qw2m4"
结论
Kubernetes RBAC 是实现集群访问控制的重要机制。通过合理配置 Role、RoleBinding、ClusterRole 和 ClusterRoleBinding,可以有效管理用户权限与系统安全之间的关系。定期测试和验证权限配置,有助于保持 Kubernetes 环境的稳定性和安全性。