Skip to main content

Authorization modes

ModeDescription
AlwaysAllowAllows all requests without any authorization checks
AlwaysDenyBlocks all requests
Node AuthorizationAuthorizes API requests made by kubelets
ABACGrants access based on policies combining user attributes
RBACRegulates access based on roles assigned to users or service accounts
WebhookDelegates authorization to an external service (e.g., Open Policy Agent)
By default, kube-apiserver uses AlwaysAllow. You can change the mode with --authorization-mode. Multiple modes can be specified as a comma-separated list — the apiserver tries each mode in order and denies the request only if all modes deny it.
--authorization-mode=RBAC,ABAC,Webhook

Node authorization

The node authorizer only handles requests from kubelets.
The node authorizer grants kubelets privileges to perform API operations. Kubelets are part of the system:node group and have names prefixed with system:node. Read operations granted:
  • services, endpoints, nodes, pods
  • secrets, configmaps, persistent volume claims, and persistent volumes related to pods on the kubelet’s node
Write operations granted:
  • node status, pod status, events

Attribute-based access control (ABAC)

ABAC restricts access using a static policy file that defines rules based on user attributes. Note that every policy change requires restarting the kube-apiserver.
1

Create a policy file

The following example policy file:
  • Allows Alice to create and get pods in the default namespace
  • Allows Bob to get pods in the prod namespace (read-only)
  • Allows the dev group to access all resources in all namespaces
policy.jsonl
{"apiVersion": "abac.authorization.kubernetes.io/v1beta1", "kind": "Policy", "spec": { "user": "alice", "namespace": "default", "resource": "pods", "readonly": false}}
{"apiVersion": "abac.authorization.kubernetes.io/v1beta1", "kind": "Policy", "spec": {"user": "bob", "namespace": "prod", "resource": "pods", "readonly": true}}
{"apiVersion": "abac.authorization.kubernetes.io/v1beta1", "kind": "Policy", "spec": {"group": "dev", "namespace": "*", "resource": "*"}}
2

Enable ABAC mode on the kube-apiserver

/etc/kubernetes/manifests/kube-apiserver.yaml
--authorization-mode=ABAC
--authorization-policy-file=policy.jsonl
Mount the policy file as a volume so the kube-apiserver can access it. Every time you update the policy file, you must restart the kube-apiserver.
3

Create a user and test permissions

# Create a service account to act as the user
kubectl create serviceaccount alice
Create a service account token:
sa-token-secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: alice-token
  annotations:
    kubernetes.io/service-account.name: alice
type: kubernetes.io/service-account-token
Retrieve and store the token:
kubectl get secret alice-token -o jsonpath='{.data.token}' | base64 --decode > token.txt
Set up user credentials and context:
export ALICE_TOKEN=$(cat token.txt)
kubectl config set-credentials alice --token=$ALICE_TOKEN
kubectl config set-context alice-context --user=alice --cluster=kubernetes --namespace=default
Verify permissions:
kubectl get pods -n default      # should succeed
kubectl get secrets -n default   # should be denied

Role-based access control (RBAC)

RBAC is primarily used to authorize users or service accounts for namespace-scoped resources.
RBAC lets you define a Role with a set of permissions, then bind it to users, groups, or service accounts. Before creating roles, identify whether resources are namespace-scoped or cluster-scoped:
# List all namespace-scoped resources
kubectl api-resources --namespaced=true

# Include verbs in the output
kubectl api-resources --namespaced=true --sort-by name -o wide
Roles and RoleBindings are themselves namespace-scoped. If no namespace is specified, they are created in the default namespace.
1

Create a Role

role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: developer
rules:
  - apiGroups: [""]          # "" indicates the core API group
    resources: ["pods"]
    verbs: ["get", "watch", "list"]
  - apiGroups: ["apps"]
    resources: ["deployments"]
    verbs: ["create", "delete"]
  - apiGroups: [""]
    resources: ["secrets"]
    verbs: ["get"]
    resourceNames: ["secret-name", "my-secret"]  # optional: restrict to specific resource names
  • apiGroups — the API group of the resource (see the API Version column from kubectl api-resources)
  • resourceNames — restricts the rule to specific named resources; omit to apply to all resources of that type
kubectl create role developer --verb=get,watch,list --resource=pods
kubectl create role developer --verb=create,delete --resource=deployments.apps
kubectl create role developer --verb=get --resource=secrets \
  --resource-name=secret-name --resource-name=my-secret

kubectl get roles
2

Create a RoleBinding

Link the role to a user, group, or service account.
rolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: developer-binding
subjects:
  - kind: User
    name: user1
    apiGroup: rbac.authorization.k8s.io
  - kind: Group
    name: backend-developers
    apiGroup: rbac.authorization.k8s.io
  - kind: ServiceAccount
    name: my-service-account
    namespace: default
  - kind: Group
    name: system:serviceaccounts:default   # all service accounts in the default namespace
    apiGroup: rbac.authorization.k8s.io
  - kind: Group
    name: system:serviceaccounts          # all service accounts in any namespace
    apiGroup: rbac.authorization.k8s.io
  - kind: Group
    name: system:authenticated            # all authenticated users
    apiGroup: rbac.authorization.k8s.io
  - kind: Group
    name: system:unauthenticated          # all unauthenticated users
    apiGroup: rbac.authorization.k8s.io
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role                              # Role or ClusterRole
  name: developer
You can reference a ClusterRole in a RoleBinding to reuse a common set of permissions across multiple namespaces without duplicating role definitions.
kubectl create rolebinding developer-binding --role=developer --user=user1
kubectl create rolebinding developer-binding --role=developer --group=backend-developers
kubectl create rolebinding developer-binding --role=developer \
  --serviceaccount=default:my-service-account

kubectl get rolebinding
3

Verify access (optional)

kubectl auth can-i delete nodes
kubectl auth can-i get pods --as developer

# Check if a user can create deployments in the prod namespace
kubectl auth can-i create deployments --as developer --namespace prod

# Check if a group can delete nodes
kubectl auth can-i delete nodes --as-group=developers

# Check if a service account can get pods
kubectl auth can-i get pods --as=system:serviceaccount:default:my-service-account

# Check if a service account can create deployments in the prod namespace
kubectl auth can-i create deployments \
  --as=system:serviceaccount:default:my-service-account --namespace=prod

Build docs developers (and LLMs) love