Authentication and Authorization¶
In Kubernetes, every API request is evaluated through access control stages before it is accepted.
For day-to-day operations, understanding Authentication and Authorization is mandatory for secure troubleshooting and platform reliability.
What It Is¶
Kubernetes API access control follows this order:
- Authentication: who is making the request?
- Authorization: is this identity allowed to do this action?
- Admission: should the request be modified or rejected before persistence?
Authentication and Authorization are related but distinct:
- Authentication identifies the caller (user, group, service account)
- Authorization decides what that identity can do (verbs, resources, namespaces, non-resource URLs)
Important fundamentals:
- Kubernetes has no native "User" object for normal users
- Normal users are managed externally (OIDC, certificates, proxies, webhooks, etc.)
- Service accounts are Kubernetes-native identities for workloads
- Authorization is deny-by-default unless explicitly allowed
When to Use It¶
Use this guide when:
- A request fails with
Unauthorized(401) orForbidden(403) - A service account cannot access required resources
- You need least-privilege RBAC for workloads or teams
- You need to validate permissions before rollout
- You are migrating or reviewing auth/authz control-plane configuration
Core Commands¶
Verify Current Identity¶
kubectl config current-context
kubectl config view --minify
kubectl auth whoami
kubectl auth whoami -o json
Why it matters:
- Confirms which user/service-account attributes are currently in effect
- Prevents debugging the wrong context or wrong identity
Check Effective Permissions Quickly¶
kubectl auth can-i create pods -n dev
kubectl auth can-i list deployments.apps -n prod
kubectl auth can-i get /livez
kubectl auth can-i get /readyz
kubectl auth can-i --list -n dev
With impersonation (great for validation):
kubectl auth can-i list pods --as=system:serviceaccount:dev:app-sa -n dev
Why it matters:
- Fastest practical check for authorization behavior
- Uses server-side review APIs and works across authorization modes
Note:
- Prefer
/livezand/readyzfor API server health-related non-resource checks. /healthzis deprecated.
Create Namespace-Scoped RBAC (Role + RoleBinding)¶
kubectl create role pod-reader --verb=get,list,watch --resource=pods -n dev
kubectl create rolebinding app-read-pods \
--role=pod-reader \
--serviceaccount=dev:app-sa \
-n dev
Why it matters:
- Enforces least privilege in a single namespace
- Standard pattern for most application service accounts
Create Cluster-Scoped RBAC (ClusterRole + ClusterRoleBinding)¶
kubectl create clusterrole node-reader --verb=get,list,watch --resource=nodes
kubectl create clusterrolebinding app-read-nodes \
--clusterrole=node-reader \
--serviceaccount=dev:app-sa
Why it matters:
- Needed for cluster-wide resources
- Must be used carefully to avoid privilege overreach
Inspect RBAC Objects and Subjects¶
kubectl get role,rolebinding -n dev
kubectl get clusterrole,clusterrolebinding
kubectl describe rolebinding app-read-pods -n dev
kubectl describe clusterrolebinding app-read-nodes
Why it matters:
- Reveals subject/role mismatches quickly
- Shows exactly what is bound to whom
Service Account Identity and Tokens¶
kubectl get sa -n dev
kubectl describe sa app-sa -n dev
kubectl create token app-sa -n dev
Why it matters:
- Validates workload identity wiring
kubectl create tokenuses modern token flows instead of relying on legacy static secret tokens
Validate Access Using Review APIs (Explicit)¶
apiVersion: authorization.k8s.io/v1
kind: SelfSubjectAccessReview
spec:
resourceAttributes:
group: apps
resource: deployments
verb: create
namespace: dev
Apply:
kubectl create -f selfsubjectaccessreview.yaml -o yaml
Why it matters:
- Gives explicit allow/deny result from the API server
- Useful in automation and policy diagnostics
Control-Plane Configuration (Cluster Admin Context)¶
Authentication configuration:
--authentication-configwithAuthenticationConfiguration(apiserver.config.k8s.io/v1)
Authorization configuration:
--authorization-configwithAuthorizationConfiguration(apiserver.config.k8s.io/v1)
Why it matters:
- Structured config is the modern path for advanced authn/authz configuration
- Avoids drift and improves auditability compared to scattered flags
Real-World Example¶
Scenario: an app in namespace dev fails with 403 Forbidden when listing Pods.
- Confirm caller identity:
kubectl auth whoami
kubectl get pod app-xyz -n dev -o yaml | rg serviceAccountName
- Confirm effective access for the workload identity:
kubectl auth can-i list pods --as=system:serviceaccount:dev:app-sa -n dev
- Inspect bindings:
kubectl get rolebinding -n dev
kubectl describe rolebinding app-read-pods -n dev
- Fix RBAC scope mismatch (for example binding in wrong namespace), then re-check:
kubectl auth can-i list pods --as=system:serviceaccount:dev:app-sa -n dev
- Validate app behavior and logs after access is allowed.
Likely outcomes:
- Missing RoleBinding
- Binding to wrong namespace/service account name
- Role verbs/resources incomplete for required API action
Debugging Pattern¶
Use this sequence for access-control incidents:
- Identify status code first:
401vs403 - Confirm identity (
kubectl auth whoami, service account on PodSpec) - Test permissions (
kubectl auth can-i ...) - Inspect Role/ClusterRole and bindings
- Verify namespace scope and subject strings exactly
- Re-test with impersonation and minimal required verb/resource
Diagnostic shortcuts:
401 Unauthorized: authentication failure (bad/expired/missing credentials)403 Forbidden: authenticated identity lacks permission- Works with your user but fails in Pod: service account RBAC mismatch
- Intermittent failures: token expiration/rotation or admission/policy side effects
Common Pitfalls¶
- Treating authentication and authorization as the same problem
- Granting
cluster-admininstead of creating least-privilege roles - Forgetting namespace scope on Roles/RoleBindings
- Mis-typing service account subjects (
system:serviceaccount:<ns>:<name>) - Assuming role exists means access exists (binding is what grants access)
- Using legacy, long-lived service account token secret patterns by default
- Ignoring impersonation checks before applying production RBAC changes