RBAC Authorization Pipeline & Mental Model
Vì Sao Quan Trọng Ở Production
Rất nhiều engineers giả định RBAC authorization là "đơn giản: match role vs. verb, return allow/deny". Thực tế, Kubernetes authorization pipeline là stateful, multi-stage, fail-secure-by-default mechanism với subtle semantics:
- Fail-secure default — nếu không authorizer nào approve request, system tự động deny, không có "default allow"
- Authorization mode chain — API server có thể cấu hình multiple authorizers (RBAC, Webhook, ABAC). Chúng hoạt động theo thứ tự, và semantic của chúng khác nhau
- Privilege escalation prevention — Kubernetes enforce ràng buộc: users không thể cấp cho bản thân quyền mà bản thân không có
- Impersonation tracking — khi request chạy dưới delegated identity, audit trail phải capture cả original requester lẫn impersonated subject
Ở scale, nếu RBAC design sai ở mức mental model này, các lỗi sẽ lặp lại hàng loạt:
- Over-privileged service accounts vì "grant cluster-admin to be safe"
- Audit trails không trackable vì delegation chain không clear
- Operational overheads khi authorization decisions phải custom-coded vào webhook
Kubernetes Authorization Architecture
High-Level Authorization Flow
Khi request tới API server, trước khi nó được process, API server chạy qua authorization stage:
Client Request
↓
[Authentication] — Ai bạn? (đặt identity vào context)
↓
[Authorization] — Bạn có quyền không? ← WE ARE HERE
↓
[Mutation Admission] — Valid không?
↓
[Validating Admission] — Check constraints
↓
[Persist to etcd]Authorization pipeline chuyên biệt cho việc answer câu hỏi: "Liệu request này (từ user/service-account nhất định, thực hiện verb nhất định, trên resource nhất định) có được phép không?"
Request Attributes Available to Authorization
Khi API server evaluates authorization decision, nó có toàn bộ request context:
Request Attributes {
user:
username: "alice@example.com"
uid: "123-456-789"
groups: ["developers", "system:authenticated"]
extra: {...} // extra attributes from authenticator
action:
verb: "create"
apiGroup: "apps"
resource: "deployments"
namespace: "default"
name: "my-deployment"
subresource: "" // or "status", "logs", etc.
source: {
IP: "10.0.0.5"
userAgent: "kubectl/v1.30"
}
}Mỗi authorizer (RBAC, Webhook, ABAC) sẽ evaluate request dựa trên những attributes này.
Authorization Modes & Chain Semantics
Kubernetes cho phép cấu hình multiple authorizers thông qua --authorization-mode flag. Chúng hoạt động tuần tự, với semantics fail-open-for-no-opinion, fail-closed-for-deny:
Input: Request with attributes
↓
For each authorizer in chain (in order):
decision = authorizer.authorize(request)
if decision == ALLOW:
return ALLOW ← Short-circuit, other authorizers skipped
else if decision == DENY:
return DENY ← Short-circuit, other authorizers skipped
else if decision == NO_OPINION:
continue to next authorizer
If no authorizer approved:
return DENY ← Fail-secure defaultVí Dụ: Chain Semantics
Giả sử config: --authorization-mode=RBAC,Webhook,AlwaysAllow
Scenario 1: Request create Pod trong default namespace
| Authorizer | Decision | Action |
|---|---|---|
| RBAC | ALLOW (match role) | SHORT-CIRCUIT → ALLOW |
| Webhook | (skipped) | |
| AlwaysAllow | (skipped) |
Scenario 2: Request list Secrets
| Authorizer | Decision | Action |
|---|---|---|
| RBAC | NO_OPINION (no matching rule) | Continue |
| Webhook | DENY (policy blocks secret access) | SHORT-CIRCUIT → DENY |
| AlwaysAllow | (skipped) |
Scenario 3: Request (with AlwaysAllow first: DANGEROUS)
--authorization-mode=AlwaysAllow,RBAC,Webhook| Authorizer | Decision | Action |
|---|---|---|
| AlwaysAllow | ALLOW (always) | SHORT-CIRCUIT → ALLOW ✗ |
| RBAC | (skipped) | |
| Webhook | (skipped) |
DANGER: Nếu AlwaysAllow first, nó sẽ always approve, bypass tất cả authorization tính toán sau. Đây là classic misconfiguration gotcha.
RBAC Authorization: Rules Matching
RBAC rule matching follows OR semantics: if request matches ANY rule, decision là ALLOW.
Rule Structure
Một RBAC rule trong ClusterRole/Role có dạng:
rules:
- apiGroups: ["apps", ""] # API groups
resources: ["pods", "services"] # Resources (what)
verbs: ["get", "list", "create"] # Actions (how)
resourceNames: [] # Optional: limit to specific names
namespaces: [] # (Not in RBAC rule itself, scoped by Binding)Matching Algorithm
Để check nếu request (verb, apiGroup, resource, namespace, name) được allow:
For each ClusterRoleBinding in cluster:
For each binding.subject:
if subject matches request.user or request.groups:
For each ClusterRole rule:
if rule.verbs contains request.verb
AND rule.apiGroups contains request.apiGroup
AND rule.resources contains request.resource
AND (rule.resourceNames is empty OR rule.resourceNames contains request.name):
return ALLOW
For each RoleBinding in request.namespace:
(same logic as above, but bounded to that namespace)
return DENYKey points:
- Wildcard support:
"*"trong apiGroups/resources/verbs match anything - Resource names limitation: nếu
resourceNamesspecified, request phải match cái tên cụ thể - Namespace scoping: RoleBinding restrict rule scope tới binding's namespace
Verb Mapping from HTTP
Kubernetes internally translate HTTP method → verb:
| HTTP | Verbs | When |
|---|---|---|
| GET /api/v1/pods/my-pod | get | Fetch single resource |
| GET /api/v1/pods | list | Fetch collection |
| GET /api/v1/pods?watch=true | watch | Streaming watch |
| POST /api/v1/pods | create | Create |
| PUT /api/v1/pods/my-pod | update | Replace (full) |
| PATCH /api/v1/pods/my-pod | patch | Partial update |
| DELETE /api/v1/pods/my-pod | delete | Delete single |
| DELETE /api/v1/pods | deletecollection | Delete multiple |
Important: watch verb phải explicitly grant. Default RBAC rules không include watch, dù list granted.
Privilege Escalation Prevention
Kubernetes enforce strong constraint: users không thể grant bản thân quyền mà bản thân không có. Cơ chế này prevent escalation.
The escalate & bind Verbs
Hai special verbs control privilege grants:
escalateverb — trênroleshoặcclusterrolesresource- User phải có
escalatepermission trên role để grant rules từ role đó - Chỉ admins mới có
escalatepermission (defined by default cluster roles) - Nếu user không có
escalate, họ không thể create/update rule mà "escalates" privilege
- User phải có
bindverb — trênrolebindingshoặcclusterrolebindingsresource- User phải có
bindpermission để create RoleBinding/ClusterRoleBinding - Ngoài ra, user phải có
escalatetrên role đó (checked implicitly) - Nếu user không có quyền được grant, họ không thể bind role đó cho subject lain
- User phải có
Practical Example
Alice là developer có permission: pods: [get, list, create] trong default namespace.
Alice không thể:
# Attempt 1: Alice tạo ClusterRole mà grant secret:get
kubectl create clusterrole secret-reader --verb=get --resource=secrets
# → DENIED (Alice không có escalate trên clusterroles)
# Attempt 2: Alice tạo RoleBinding gán cluster-admin tới bản thân
kubectl create rolebinding alice-admin --clusterrole=cluster-admin --user=alice
# → DENIED (Alice không có bind trên cluster-admin, vì Alice không admin)
# Attempt 3: Alice tạo RoleBinding gán pod reader tới bạn
kubectl create rolebinding bob-pods --role=pod-reader --user=bob
# → DENIED (nếu pod-reader có quyền hơn Alice's permissions)Cơ chế checks:
When Alice tries to bind role R to user U:
1. Does Alice have "bind" on rolebindings? → NO → DENY
2. (If yes) Does Alice have all verbs in role R's rules?
→ If NO → DENY (prevent escalation)
→ If YES → ALLOW bindConstraint này enforce transitive privilege boundaries — user chỉ có thể grant subset của quyền họ có.
Authorization with Service Accounts & Impersonation
Service accounts (SAs) là first-class subjects trong RBAC. Ngoài direct role assignment, Kubernetes support impersonation — delegated authorization.
Service Account Identity
Mỗi SA tại namespace ns có identity:
Username: system:serviceaccount:<namespace>:<name>
Groups:
- system:serviceaccounts
- system:serviceaccounts:<namespace>
- system:authenticatedVí dụ SA my-app ở namespace production:
Username: system:serviceaccount:production:my-app
Groups:
- system:serviceaccounts
- system:serviceaccounts:production
- system:authenticatedKhi kubelet authenticate Pod dùng SA token, API server set request.user thành SA identity này.
Impersonation Mechanism
Users hoặc service accounts có thể "impersonate" subject khác (user, group, SA) nếu họ có permission:
verb: "impersonate"
resource: "users" | "groups" | "serviceaccounts" | "userextras"Flow:
User A (authenticated, có impersonate permission) gọi API với header:
Impersonate-User: system:serviceaccount:default:my-app Impersonate-Group: developersAPI server checks: "Liệu User A có impersonate verb trên serviceaccounts resource?"
if request.user has {verb: impersonate, resource: serviceaccounts}: use Impersonate-User as request identity else: denyRequest được evaluate as if from
system:serviceaccount:default:my-app, nhưng audit log track cả original user (A) lẫn impersonated user.
Privilege escalation prevention khi impersonate:
When User A impersonates User B:
1. Does A have impersonate verb? → Check
2. Does A have all groups that B would have?
→ If B trong group G, and A không có G → DENYCơ chế này prevent users from impersonating more-privileged users.
Authorization Failure Modes & Debugging
Common Mistakes
Mistake 1: Assuming wildcard in rules
rules:
- verbs: ["*"]
resources: ["*"]
apiGroups: ["*"]Developer expect điều này match tất cả. Nhưng thực tế:
"*"không match resources nhưclusterroles,roles,rolebindings(core API group mà không specify explicitly)- Solution: explicit specify
["rbac.authorization.k8s.io"]in apiGroups
Mistake 2: Over-broad verbs
rules:
- verbs: ["*"]
resources: ["pods"]Cho phép exec, logs, portforward, mà developer không intend. Better:
rules:
- verbs: ["get", "list"]
resources: ["pods"]
- verbs: ["create", "get"]
resources: ["pods/exec"]Mistake 3: Namespace isolation broken
# Risky pattern
kind: RoleBinding
metadata:
namespace: default
roleRef:
kind: ClusterRole
name: cluster-admin # Cluster-scope roleDù ClusterRole, binding restrict tới default namespace. Nhưng cluster-admin là too broad for namespace scope.
Debugging Authorization Denies
Khi authorization denied:
Check audit log — enable audit logging:
--audit-log-path=/var/log/audit.log --audit-policy-file=/etc/kubernetes/audit-policy.yamlLook for decision:
deny, reasonCheck subject identity — impersonation applied?
bashkubectl auth can-i create pods --as=system:serviceaccount:default:my-appCheck role bindings — subject matched any binding?
bashkubectl get rolebindings -A | grep my-appCheck role rules — verb+resource matched?
bashkubectl describe role pod-reader
System Groups & Bootstrap
Kubernetes define special system groups:
| Group | Members | Scope |
|---|---|---|
system:authenticated | All authenticated users & SAs | Cluster-wide |
system:unauthenticated | Requests without token | (Dangerous; usually denied) |
system:serviceaccounts | All SAs cluster-wide | Cluster-wide |
system:serviceaccounts:ns | SAs in namespace ns | Namespace |
system:masters | (Not membership; special) | Bypass all auth |
system:masters Special Case
system:masters group member bypass authorization entirely. Nó digunakan để bootstrap (kubelet bootstrap credentials). Di production:
# DO NOT do this
kind: ClusterRoleBinding
metadata:
name: admin-via-masters
roleRef:
kind: ClusterRole
name: cluster-admin
subjects:
- kind: Group
name: system:mastersNày will bypass tất cả authorization checks. Use sparingly; usually không diperlukan.
Constraints & Limitations
What RBAC CAN'T Do
Kubernetes RBAC là resource-level, verb-level authorization only. Không có thể:
- Field-level authorization — "Allow read status.conditions, deny status.errors"
- Time-bound permissions — "Expire role grant after 24 hours"
- Quota enforcement — handled by ResourceQuota, không phải RBAC
- Business logic — "Allow create if resource label matches user"
Nếu need lebih fine-grained, use Webhook authorization hoặc Admission controllers.
Webhook vs. RBAC
| Aspect | RBAC | Webhook |
|---|---|---|
| Decision speed | In-process, fast | External call, slower |
| Complexity | Rule matching | Arbitrary logic |
| Auditability | Built-in audit | Must log in webhook |
| Failure handling | Deny (safe) | Configurable (allow/deny on timeout) |
| Scaling | No external dependency | Scales with webhook server |
RBAC sufficient để 90% use cases. Webhook diperlukan để complex custom logic.
Summary: Mental Model
Kubernetes authorization là stateless matching engine mà:
- Extracts request attributes (user, groups, verb, resource, namespace)
- Runs authorization chain (RBAC → Webhook → ...)
- Matches request against rules
- Enforces privilege escalation prevention (escalate verb, impersonation transitive check)
- Returns ALLOW hoặc DENY (fail-secure default)
Inti từ design:
- Fail-secure: no approval = deny
- Privilege boundary: users có thể't escalate
- Auditability: every decision trackable
- Composability: multiple authorizers chain