RBAC 授权机制深度解析
RBAC 授权机制深度解析
快速参考
核心概念速览
- Role: 命名空间级别的权限集合
- ClusterRole: 集群级别的权限集合
- RoleBinding: 将 Role 绑定到用户/组/ServiceAccount
- ClusterRoleBinding: 将 ClusterRole 绑定到用户/组/ServiceAccount
常用命令
# 检查权限
kubectl auth can-i create pods --as=alice
kubectl auth can-i delete deployments --as=alice -n production
# 列出所有权限
kubectl auth can-i --list -n production
# 查看角色
kubectl get roles,clusterroles
kubectl describe role <role-name>
RBAC 概述
RBAC (Role-Based Access Control) 是 Kubernetes 中最常用的授权机制,通过角色和绑定来控制用户或服务账户的权限。
RBAC 模型
┌──────────────────────────────────────────────┐
│ RBAC 模型 │
├──────────────────────────────────────────────┤
│ │
│ Subject (主体) │
│ ├─ User (用户) │
│ ├─ Group (组) │
│ └─ ServiceAccount (服务账户) │
│ │ │
│ ▼ │
│ RoleBinding / ClusterRoleBinding │
│ (绑定关系) │
│ │ │
│ ▼ │
│ Role / ClusterRole │
│ (权限集合) │
│ ├─ API Groups │
│ ├─ Resources │
│ └─ Verbs (get, list, create...) │
│ │
└──────────────────────────────────────────────┘
RBAC 资源类型
1. Role(命名空间级别)
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: pod-reader
namespace: default
rules:
- apiGroups: [""] # "" 表示 core API group
resources: ["pods"]
verbs: ["get", "watch", "list"]
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "list"]
resourceNames: ["nginx"] # 限制特定资源名称
2. ClusterRole(集群级别)
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: cluster-reader
rules:
- apiGroups: [""]
resources: ["nodes", "persistentvolumes"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["namespaces"]
verbs: ["get", "list"]
- apiGroups: ["apps"]
resources: ["deployments", "daemonsets", "statefulsets"]
verbs: ["get", "list", "watch"]
- nonResourceURLs: ["/metrics", "/healthz"]
verbs: ["get"]
3. RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: read-pods
namespace: default
subjects:
# 用户
- kind: User
name: jane
apiGroup: rbac.authorization.k8s.io
# 组
- kind: Group
name: developers
apiGroup: rbac.authorization.k8s.io
# ServiceAccount
- kind: ServiceAccount
name: app-sa
namespace: default
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io
4. ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: cluster-admin-binding
subjects:
- kind: User
name: admin
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: cluster-admin
apiGroup: rbac.authorization.k8s.io
授权流程源码分析
API Server 授权检查
// k8s.io/apiserver/pkg/endpoints/filters/authorization.go
func WithAuthorization(handler http.Handler, a authorizer.Authorizer) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
ctx := req.Context()
// 1. 获取请求属性
attributes := authorizer.AttributesRecord{
User: authenticatedUser,
Verb: verb, // get, list, create, etc.
Namespace: namespace,
APIGroup: apiGroup,
APIVersion: apiVersion,
Resource: resource,
Subresource: subresource,
Name: name,
ResourceRequest: isResourceRequest,
Path: req.URL.Path,
}
// 2. 执行授权检查
authorized, reason, err := a.Authorize(ctx, attributes)
// 3. 处理授权结果
if authorized != authorizer.DecisionAllow {
http.Error(w, fmt.Sprintf("Forbidden: %s", reason), http.StatusForbidden)
return
}
// 4. 授权通过,继续处理请求
handler.ServeHTTP(w, req)
})
}
RBAC 授权器实现
// k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/rbac.go
type RBACAuthorizer struct {
authorizationRuleResolver *rbacregistryvalidation.AuthorizationRuleResolver
}
func (r *RBACAuthorizer) Authorize(ctx context.Context, requestAttributes authorizer.Attributes) (authorizer.Decision, string, error) {
// 1. 获取用户信息
user := requestAttributes.GetUser()
// 2. 收集用户的所有角色
rules, err := r.GetRoleReferenceRules(user, requestAttributes.GetNamespace())
if err != nil {
return authorizer.DecisionNoOpinion, "", err
}
// 3. 检查是否有匹配的规则
if RulesAllow(requestAttributes, rules...) {
return authorizer.DecisionAllow, "", nil
}
return authorizer.DecisionNoOpinion, "no matching rule found", nil
}
// 检查规则是否匹配
func RulesAllow(requestAttributes authorizer.Attributes, rules ...rbacv1.PolicyRule) bool {
for _, rule := range rules {
if RuleAllows(requestAttributes, rule) {
return true
}
}
return false
}
func RuleAllows(requestAttributes authorizer.Attributes, rule rbacv1.PolicyRule) bool {
// 1. 检查 API Group
if !apiGroupMatches(&rule, requestAttributes.GetAPIGroup()) {
return false
}
// 2. 检查 Resource
if !resourceMatches(&rule, requestAttributes.GetResource(), requestAttributes.GetSubresource()) {
return false
}
// 3. 检查 Verb
if !verbMatches(&rule, requestAttributes.GetVerb()) {
return false
}
// 4. 检查 ResourceName(如果指定)
if !resourceNameMatches(&rule, requestAttributes.GetName()) {
return false
}
return true
}
内置 ClusterRole
查看内置角色
# 查看所有 ClusterRole
kubectl get clusterroles
# 常用内置 ClusterRole
kubectl get clusterrole cluster-admin -o yaml
kubectl get clusterrole edit -o yaml
kubectl get clusterrole view -o yaml
关键内置角色
| ClusterRole | 权限范围 | 适用场景 |
|---|---|---|
cluster-admin |
完全控制权限 | 集群管理员 |
admin |
命名空间管理权限 | 命名空间管理员 |
edit |
读写权限(不包括 Role/RoleBinding) | 开发者 |
view |
只读权限 | 只读用户 |
system:node |
Node 组件权限 | kubelet |
system:kube-scheduler |
Scheduler 权限 | kube-scheduler |
ServiceAccount RBAC
创建 ServiceAccount
apiVersion: v1
kind: ServiceAccount
metadata:
name: app-sa
namespace: default
绑定权限
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: app-role
namespace: default
rules:
- apiGroups: [""]
resources: ["pods", "services"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["configmaps"]
verbs: ["get"]
resourceNames: ["app-config"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: app-binding
namespace: default
subjects:
- kind: ServiceAccount
name: app-sa
namespace: default
roleRef:
kind: Role
name: app-role
apiGroup: rbac.authorization.k8s.io
Pod 使用 ServiceAccount
apiVersion: v1
kind: Pod
metadata:
name: app-pod
namespace: default
spec:
serviceAccountName: app-sa
containers:
- name: app
image: myapp
在 Pod 中访问 API Server
# ServiceAccount Token 自动挂载到 Pod
TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
CACERT=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
APISERVER=https://kubernetes.default.svc
# 使用 Token 访问 API
curl --cacert $CACERT --header "Authorization: Bearer $TOKEN" \
$APISERVER/api/v1/namespaces/default/pods
权限聚合
Aggregate ClusterRole
# 定义一个聚合角色
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: monitoring-role
labels:
rbac.example.com/aggregate-to-monitoring: "true"
rules:
- apiGroups: [""]
resources: ["pods", "services", "endpoints"]
verbs: ["get", "list", "watch"]
---
# 聚合规则
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: monitoring
aggregationRule:
clusterRoleSelectors:
- matchLabels:
rbac.example.com/aggregate-to-monitoring: "true"
rules: [] # 自动从匹配的 ClusterRole 聚合
扩展内置角色
# 扩展 view 角色
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: view-custom-resources
labels:
rbac.authorization.k8s.io/aggregate-to-view: "true"
rules:
- apiGroups: ["mycompany.com"]
resources: ["myresources"]
verbs: ["get", "list", "watch"]
权限审计
检查用户权限
# 检查当前用户是否有某个权限
kubectl auth can-i create deployments
kubectl auth can-i list pods --namespace=default
# 检查指定用户的权限
kubectl auth can-i create deployments --as=jane
kubectl auth can-i list pods --as=system:serviceaccount:default:app-sa
# 检查所有权限
kubectl auth can-i --list
kubectl auth can-i --list --namespace=default
查看有效权限
# 查看用户的所有 RoleBinding
kubectl get rolebindings,clusterrolebindings \
--all-namespaces \
-o json | jq '.items[] | select(.subjects[]?.name=="jane")'
# 查看 ServiceAccount 的权限
kubectl describe sa app-sa -n default
kubectl get rolebindings,clusterrolebindings --all-namespaces \
-o json | jq '.items[] | select(.subjects[]?.name=="app-sa")'
最小权限原则实践
❌ 反模式:过大权限
# 不推荐:给予 cluster-admin 权限
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: developer-admin
subjects:
- kind: User
name: developer
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: cluster-admin # ⚠️ 危险:完全控制权限
apiGroup: rbac.authorization.k8s.io
问题:
- 开发者拥有删除整个集群的权限
- 无法追踪具体操作范围
- 违反最小权限原则
✅ 推荐:精确权限控制
1. 应用只读权限
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: app-reader
namespace: production
rules:
- apiGroups: [""]
resources: ["configmaps"]
verbs: ["get"]
resourceNames: ["app-config"] # 只读特定 ConfigMap
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get"]
resourceNames: ["app-secret"] # 只读特定 Secret
2. 开发者完整权限
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: developer
namespace: dev
rules:
# Pod 相关
- apiGroups: [""]
resources: ["pods", "pods/log", "pods/exec"]
verbs: ["get", "list", "watch", "create", "delete"]
# 应用部署
- apiGroups: ["apps"]
resources: ["deployments", "replicasets"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
# Service
- apiGroups: [""]
resources: ["services"]
verbs: ["get", "list", "watch", "create", "update", "patch"]
# ConfigMap(只读)
- apiGroups: [""]
resources: ["configmaps"]
verbs: ["get", "list"]
3. CI/CD 部署权限
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: deployer
namespace: production
rules:
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "list", "watch", "create", "update", "patch"]
- apiGroups: [""]
resources: ["services"]
verbs: ["get", "list", "create", "update"]
- apiGroups: [""]
resources: ["configmaps", "secrets"]
verbs: ["get", "list"]
4. 监控系统权限
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: prometheus
rules:
- apiGroups: [""]
resources: ["nodes", "nodes/metrics", "services", "endpoints", "pods"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["configmaps"]
verbs: ["get"]
- nonResourceURLs: ["/metrics", "/metrics/cadvisor"]
verbs: ["get"]
权限提升攻击防御
危险的权限组合
# ⚠️ 危险:可以创建 RoleBinding 绑定任意 ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: dangerous-role
rules:
- apiGroups: ["rbac.authorization.k8s.io"]
resources: ["rolebindings"]
verbs: ["create"]
# ⚠️ 危险:可以编辑 ServiceAccount 并冒充其他身份
- apiGroups: [""]
resources: ["serviceaccounts"]
verbs: ["impersonate"]
# ⚠️ 危险:可以创建 Pod 并挂载任意 Secret
- apiGroups: [""]
resources: ["pods"]
verbs: ["create"]
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get"]
安全配置
# ✅ 安全:限制只能绑定特定的 Role
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: safe-role-manager
rules:
- apiGroups: ["rbac.authorization.k8s.io"]
resources: ["rolebindings"]
verbs: ["create", "update"]
resourceNames: ["app-reader", "app-editor"] # 只能绑定这些 Role
调试 RBAC 问题
启用审计日志
# audit-policy.yaml
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: Metadata
verbs: ["create", "update", "patch", "delete"]
omitStages: ["RequestReceived"]
- level: Request
verbs: ["get", "list", "watch"]
resources:
- group: "rbac.authorization.k8s.io"
查看拒绝日志
# API Server 日志
kubectl logs -n kube-system kube-apiserver-master -f | grep "Forbidden"
# 审计日志
tail -f /var/log/kubernetes/audit/audit.log | jq 'select(.responseStatus.code==403)'
常见错误
# 错误 1:Forbidden
# 原因:用户没有对应权限
# 解决:检查 RoleBinding 和 ClusterRoleBinding
# 错误 2:User "system:serviceaccount:default:app-sa" cannot list pods
# 原因:ServiceAccount 缺少权限
# 解决:创建 Role 和 RoleBinding
# 错误 3:No matches for kind "Role" in version "rbac.authorization.k8s.io/v1beta1"
# 原因:API 版本过时
# 解决:使用 v1 而不是 v1beta1
RBAC 最佳实践
1. 命名约定
# ServiceAccount 命名
<component>-sa
例如:nginx-ingress-sa, prometheus-sa
# Role 命名
<namespace>-<resource>-<action>
例如:prod-pods-reader, dev-deploy-editor
# RoleBinding 命名
<role>-binding 或 <subject>-<role>
例如:pods-reader-binding, jane-editor
2. 定期审查权限
#!/bin/bash
# rbac-audit.sh
echo "=== Cluster Admin Users ==="
kubectl get clusterrolebindings -o json | \
jq -r '.items[] | select(.roleRef.name=="cluster-admin") | .subjects[]?.name'
echo "=== ServiceAccounts with cluster-admin ==="
kubectl get clusterrolebindings -o json | \
jq -r '.items[] | select(.roleRef.name=="cluster-admin") | select(.subjects[]?.kind=="ServiceAccount") | .metadata.name'
echo "=== Users with wildcard permissions ==="
kubectl get clusterroles -o json | \
jq -r '.items[] | select(.rules[]? | .resources[]? == "*") | .metadata.name'
3. 使用命名空间隔离
# 团队 A 的命名空间
apiVersion: v1
kind: Namespace
metadata:
name: team-a
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: team-a-admin
namespace: team-a
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["*"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: team-a-admin-binding
namespace: team-a
subjects:
- kind: Group
name: team-a
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: team-a-admin
apiGroup: rbac.authorization.k8s.io
总结
RBAC 是 Kubernetes 安全的基石,理解其原理对于:
- 权限管理:精确控制访问权限
- 安全加固:防止权限提升
- 故障排查:快速定位权限问题
- 合规审计:满足安全合规要求
核心原则:
- 最小权限原则:只授予必需的权限
- 职责分离:不同角色不同权限
- 定期审计:定期检查和清理权限
- 命名空间隔离:使用命名空间隔离团队