Skip to content

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: "[email protected]"
    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 default

Ví Dụ: Chain Semantics ​

Giả sử config: --authorization-mode=RBAC,Webhook,AlwaysAllow

Scenario 1: Request create Pod trong default namespace

AuthorizerDecisionAction
RBACALLOW (match role)SHORT-CIRCUIT → ALLOW
Webhook(skipped)
AlwaysAllow(skipped)

Scenario 2: Request list Secrets

AuthorizerDecisionAction
RBACNO_OPINION (no matching rule)Continue
WebhookDENY (policy blocks secret access)SHORT-CIRCUIT → DENY
AlwaysAllow(skipped)

Scenario 3: Request (with AlwaysAllow first: DANGEROUS)

--authorization-mode=AlwaysAllow,RBAC,Webhook
AuthorizerDecisionAction
AlwaysAllowALLOW (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:

yaml
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 DENY

Key points:

  • Wildcard support: "*" trong apiGroups/resources/verbs match anything
  • Resource names limitation: nếu resourceNames specified, 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:

HTTPVerbsWhen
GET /api/v1/pods/my-podgetFetch single resource
GET /api/v1/podslistFetch collection
GET /api/v1/pods?watch=truewatchStreaming watch
POST /api/v1/podscreateCreate
PUT /api/v1/pods/my-podupdateReplace (full)
PATCH /api/v1/pods/my-podpatchPartial update
DELETE /api/v1/pods/my-poddeleteDelete single
DELETE /api/v1/podsdeletecollectionDelete 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:

  1. escalate verb — trên roles hoặc clusterroles resource

    • User phải có escalate permission trên role để grant rules từ role đó
    • Chỉ admins mới có escalate permission (defined by default cluster roles)
    • Nếu user không có escalate, họ không thể create/update rule mà "escalates" privilege
  2. bind verb — trên rolebindings hoặc clusterrolebindings resource

    • User phải có bind permission để create RoleBinding/ClusterRoleBinding
    • Ngoài ra, user phải có escalate trên role đó (checked implicitly)
    • Nếu user không có quyền được grant, họ không thể bind role đó cho subject lain

Practical Example ​

Alice là developer có permission: pods: [get, list, create] trong default namespace.

Alice không thể:

bash
# 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 bind

Constraint 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:authenticated

Ví dụ SA my-app ở namespace production:

Username: system:serviceaccount:production:my-app
Groups:
  - system:serviceaccounts
  - system:serviceaccounts:production
  - system:authenticated

Khi 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:

  1. User A (authenticated, có impersonate permission) gọi API với header:

    Impersonate-User: system:serviceaccount:default:my-app
    Impersonate-Group: developers
  2. API 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:
      deny
  3. Request đượ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 → DENY

Cơ chế này prevent users from impersonating more-privileged users.

Authorization Failure Modes & Debugging ​

Common Mistakes ​

Mistake 1: Assuming wildcard in rules

yaml
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

yaml
rules:
- verbs: ["*"]
  resources: ["pods"]

Cho phép exec, logs, portforward, mà developer không intend. Better:

yaml
rules:
- verbs: ["get", "list"]
  resources: ["pods"]
- verbs: ["create", "get"]
  resources: ["pods/exec"]

Mistake 3: Namespace isolation broken

yaml
# Risky pattern
kind: RoleBinding
metadata:
  namespace: default
roleRef:
  kind: ClusterRole
  name: cluster-admin  # Cluster-scope role

Dù ClusterRole, binding restrict tới default namespace. Nhưng cluster-admin là too broad for namespace scope.

Debugging Authorization Denies ​

Khi authorization denied:

  1. Check audit log — enable audit logging:

    --audit-log-path=/var/log/audit.log
    --audit-policy-file=/etc/kubernetes/audit-policy.yaml

    Look for decision: deny, reason

  2. Check subject identity — impersonation applied?

    bash
    kubectl auth can-i create pods --as=system:serviceaccount:default:my-app
  3. Check role bindings — subject matched any binding?

    bash
    kubectl get rolebindings -A | grep my-app
  4. Check role rules — verb+resource matched?

    bash
    kubectl describe role pod-reader

System Groups & Bootstrap ​

Kubernetes define special system groups:

GroupMembersScope
system:authenticatedAll authenticated users & SAsCluster-wide
system:unauthenticatedRequests without token(Dangerous; usually denied)
system:serviceaccountsAll SAs cluster-wideCluster-wide
system:serviceaccounts:nsSAs in namespace nsNamespace
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:

yaml
# DO NOT do this
kind: ClusterRoleBinding
metadata:
  name: admin-via-masters
roleRef:
  kind: ClusterRole
  name: cluster-admin
subjects:
- kind: Group
  name: system:masters

Nà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ể:

  1. Field-level authorization — "Allow read status.conditions, deny status.errors"
  2. Time-bound permissions — "Expire role grant after 24 hours"
  3. Quota enforcement — handled by ResourceQuota, không phải RBAC
  4. 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 ​

AspectRBACWebhook
Decision speedIn-process, fastExternal call, slower
ComplexityRule matchingArbitrary logic
AuditabilityBuilt-in auditMust log in webhook
Failure handlingDeny (safe)Configurable (allow/deny on timeout)
ScalingNo external dependencyScales with webhook server

RBAC sufficient để 90% use cases. Webhook diperlukan để complex custom logic.

Summary: Mental Model ​

Kubernetes authorization là stateless matching engine mà:

  1. Extracts request attributes (user, groups, verb, resource, namespace)
  2. Runs authorization chain (RBAC → Webhook → ...)
  3. Matches request against rules
  4. Enforces privilege escalation prevention (escalate verb, impersonation transitive check)
  5. 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

Tham Khảo ​