KCSA — Authorization Modes & Best Practices

7 minute read

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:

  1. Authorizers are consulted in the order specified in --authorization-mode.
  2. If an authorizer allows the request → request is immediately allowed (no further checks).
  3. If an authorizer denies the request → the next authorizer is consulted.
  4. If an authorizer has no opinion → the next authorizer is consulted.
  5. 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.


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.

Practice Questions

Updated: