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