KCSA — Authorization Modes & Best Practices
Authorization — “What Can You Do?”
After the API server authenticates a request (determines the identity), it must authorize the action. Authorization decides whether the authenticated user is allowed to perform the requested operation on the requested resource.
Kubernetes supports multiple authorization modes. They can be used individually or in combination, forming an authorization chain.
KCSA Relevance: Know all six authorization modes, understand the authorization chain order, and be clear on why Node,RBAC is the recommended production configuration.
Authorization Modes Overview
| Mode | Description | When to Use |
|---|---|---|
| RBAC | Role-based rules — users/groups/SAs are bound to roles with explicit permissions | Always (recommended and default) |
| ABAC | Attribute-based policies defined in a JSON file | Legacy — avoid in new clusters |
| Node | Special-purpose authorizer for kubelet requests | Always enable alongside RBAC |
| Webhook | Delegates authorization decisions to an external HTTP service | Custom policy engines (OPA, Styra) |
| AlwaysAllow | Permits every request without checking | Never in production |
| AlwaysDeny | Rejects every request | Testing only |
How the Authorization Chain Works
The API server can be configured with multiple authorization modes. They are evaluated in order:
--authorization-mode=Node,RBAC
Evaluation Logic
Incoming Request
│
▼
┌────────────┐ Allow? ┌──────────┐
│ Node │ ──────────► │ ALLOWED │
│ Authorizer │ └──────────┘
└──────┬─────┘
│ No opinion / Deny
▼
┌────────────┐ Allow? ┌──────────┐
│ RBAC │ ──────────► │ ALLOWED │
│ Authorizer │ └──────────┘
└──────┬─────┘
│ No opinion / Deny
▼
┌──────────┐
│ DENIED │
└──────────┘
Key rules:
- Authorizers are consulted in the order specified in
--authorization-mode. - If an authorizer allows the request → request is immediately allowed (no further checks).
- If an authorizer denies the request → the next authorizer is consulted.
- If an authorizer has no opinion → the next authorizer is consulted.
- If no authorizer allows the request → the request is denied.
Exam Tip: The authorization chain is “first-allow wins”. A deny from one authorizer does not block the request if a later authorizer allows it.
RBAC (Role-Based Access Control)
RBAC is covered in detail in the RBAC Deep Dive topic. Here’s a summary in the context of authorization modes.
Why RBAC Is the Standard
| Advantage | Detail |
|---|---|
| Declarative | Permissions defined as Kubernetes API objects |
| Namespace-scoped | Roles can be limited to specific namespaces |
| Auditable | kubectl auth can-i and API server audit logs |
| Dynamic | Changes take effect immediately — no restart required |
| Fine-grained | Control at the resource and verb level |
| Default | Enabled by default in all major Kubernetes distributions |
Enabling RBAC
--authorization-mode=RBAC
Most clusters use --authorization-mode=Node,RBAC (see Node mode below).
Node Authorization
The Node authorizer is a special-purpose authorizer designed specifically for kubelet requests.
What It Does
The Node authorizer grants kubelets (identified as system:node:<nodeName> in group system:nodes) permission to:
| Action | Resources |
|---|---|
| Read | Services, Endpoints, Nodes, Pods (bound to their node) |
| Read | Secrets, ConfigMaps, PVCs referenced by pods on their node |
| Write | Node status, pod status |
| Write | Events |
Why Node Authorization Matters
Without Node authorization, kubelets would need broad RBAC permissions — potentially allowing a compromised node to read Secrets from pods running on other nodes.
The Node authorizer implements the principle of least privilege for kubelets: each kubelet can only access resources related to pods scheduled on its own node.
Enabling Node Authorization
--authorization-mode=Node,RBAC
This is the recommended production configuration.
ABAC (Attribute-Based Access Control)
ABAC uses a JSON policy file to define access rules based on request attributes.
Example ABAC Policy
{
"apiVersion": "abac.authorization.kubernetes.io/v1beta1",
"kind": "Policy",
"spec": {
"user": "jane",
"namespace": "development",
"resource": "pods",
"readonly": true
}
}
Why ABAC Is Discouraged
| Drawback | Impact |
|---|---|
| Requires file on control plane node | Not manageable via API |
| Requires API server restart to update | Changes are not dynamic |
| No namespace-scoping in API | Harder to delegate management |
| No built-in audit tooling | Cannot use kubectl auth can-i |
| Harder to version control | File-based, not declarative objects |
ABAC is a legacy authorization mode. Use RBAC instead for all new clusters.
Enabling ABAC
--authorization-mode=ABAC
--authorization-policy-file=/etc/kubernetes/abac-policy.json
Webhook Authorization
Webhook authorization sends authorization requests to an external HTTP service that returns allow/deny decisions.
How It Works
┌─────────────┐ SubjectAccessReview ┌──────────────────┐
│ API Server │ ───────────────────────► │ External Webhook │
│ │ │ (OPA, custom svc) │
│ │ ◄─────────────────────── │ │
│ │ allow / deny response │ │
└─────────────┘ └──────────────────┘
When to Use Webhook Authorization
| Scenario | Example |
|---|---|
| Complex multi-tenant policies | Different rules per tenant dynamically |
| Integration with policy engines | Open Policy Agent (OPA) / Gatekeeper |
| Cross-cluster authorization | Centralized authorization service |
| Regulatory compliance | Custom audit and decision logging |
Enabling Webhook Authorization
--authorization-mode=Node,RBAC,Webhook
--authorization-webhook-config-file=/etc/kubernetes/webhook-authz-config.yaml
The authorization chain evaluates Node first, then RBAC, then Webhook. This means the Webhook only sees requests that Node and RBAC didn’t explicitly allow.
AlwaysAllow and AlwaysDeny
AlwaysAllow
--authorization-mode=AlwaysAllow
Every request is authorized. This completely disables authorization.
| Risk | Impact |
|---|---|
| Any authenticated user can do anything | Full cluster access for everyone |
| No access control | No audit, no boundaries |
| All RBAC resources are ignored | Roles and bindings have no effect |
Never use AlwaysAllow in any environment with real workloads.
AlwaysDeny
--authorization-mode=AlwaysDeny
Every request is denied. This is useful only for testing or as a safety mechanism in specific authorization chain configurations.
Recommended Production Configuration
The recommended authorization mode for production Kubernetes clusters:
--authorization-mode=Node,RBAC
Why This Combination Works
| Mode | Role in the Chain |
|---|---|
| Node | Handles kubelet-specific permissions efficiently and securely |
| RBAC | Handles all other authorization decisions |
This is the default in kubeadm clusters and all major managed Kubernetes providers (EKS, GKE, AKS).
RBAC Best Practices Checklist
| # | Practice | Description |
|---|---|---|
| 1 | Start with zero permissions | Don’t grant access by default — add permissions as needed |
| 2 | Use namespace-scoped Roles | Prefer Role + RoleBinding over ClusterRole + ClusterRoleBinding |
| 3 | Avoid wildcards | Don’t use * for resources or verbs |
| 4 | Dedicated service accounts | One SA per workload, not the default SA |
| 5 | Separate read and write roles | viewer and editor roles for different access levels |
| 6 | Limit cluster-admin |
Only for emergency access, not daily operations |
| 7 | Use groups | Bind roles to groups (from OIDC/certs), not individual users |
| 8 | Regular audits | Review RBAC bindings quarterly or after team changes |
| 9 | Label-based aggregation | Use aggregated ClusterRoles for CRD permissions |
| 10 | Document RBAC decisions | Maintain a record of why each role exists |
Access Review and Audit Commands
Self-Service Checks
# What can I do in the current namespace?
kubectl auth can-i --list
# Can I create deployments in production?
kubectl auth can-i create deployments -n production
Impersonation (Admin Only)
# What can jane do in the dev namespace?
kubectl auth can-i --list --as jane -n dev
# Can the CI/CD service account delete pods in staging?
kubectl auth can-i delete pods -n staging \
--as system:serviceaccount:staging:ci-cd-sa
Finding Broad Permissions
# Who has cluster-admin?
kubectl get clusterrolebindings -o json | \
jq '.items[] | select(.roleRef.name=="cluster-admin") |
{name: .metadata.name, subjects: .subjects}'
# Which RoleBindings exist in a namespace?
kubectl get rolebindings -n production -o wide
# Which ClusterRoles use wildcards?
kubectl get clusterroles -o json | \
jq '.items[] | select(.rules[]?.resources[]? == "*") | .metadata.name'
Real-World RBAC Patterns
Pattern 1: Namespace Administrator
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: dev-ns-admin
namespace: development
subjects:
- kind: Group
name: "oidc:dev-leads"
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: admin # Built-in admin role
apiGroup: rbac.authorization.k8s.io
The dev-leads group gets full admin access within the development namespace only.
Pattern 2: Read-Only Monitoring
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: monitoring-view
subjects:
- kind: ServiceAccount
name: prometheus
namespace: monitoring
roleRef:
kind: ClusterRole
name: view # Built-in view role
apiGroup: rbac.authorization.k8s.io
Prometheus can read (but not modify) resources across all namespaces.
Pattern 3: CI/CD Deployer
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: ci-cd-deployer
namespace: production
rules:
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "list", "watch", "update", "patch"]
- apiGroups: [""]
resources: ["configmaps"]
verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: ci-cd-deployer-binding
namespace: production
subjects:
- kind: ServiceAccount
name: deploy-bot
namespace: ci-cd
roleRef:
kind: Role
name: ci-cd-deployer
apiGroup: rbac.authorization.k8s.io
The CI/CD service account can update deployments and read ConfigMaps in production — but nothing else.
Authorization Mode Comparison Summary
| Feature | RBAC | ABAC | Node | Webhook |
|---|---|---|---|---|
| API-managed | Yes | No (file) | N/A | External |
| Dynamic updates | Yes | No (restart) | N/A | Yes |
| Namespace-scoped | Yes | Limited | N/A | Depends |
Audit with can-i |
Yes | No | No | No |
| Recommended | Yes | No | Yes | When needed |
| Default in kubeadm | Yes | No | Yes | No |
Key Takeaways for the Exam
| Concept | What to Remember |
|---|---|
| Six authorization modes | RBAC, ABAC, Node, Webhook, AlwaysAllow, AlwaysDeny |
| Recommended config | --authorization-mode=Node,RBAC |
| Authorization chain | First authorizer to allow wins; deny passes to next |
| RBAC is the standard | Declarative, dynamic, auditable, namespace-scoped |
| Node authorizer | Limits kubelet to resources on its own node |
| ABAC is legacy | File-based, requires restart — avoid |
| Webhook | Delegates to external service (e.g., OPA) |
| AlwaysAllow | Never in production — disables all authorization |
| Least privilege | Start with zero permissions — add incrementally |
What’s Next?
You’ve completed all five topics in the Authentication & Authorization chapter. Test your knowledge with the practice questions.