What is RBAC?
RBAC (Role-Based Access Control) is how you manage permissions in Kubernetes. It controls:
- Who can access the cluster (authentication via K8s API)
- What they can do (authorization via RBAC)
- On which resources (Pods, Deployments, Secrets, etc.)
Security principle: Always follow the Principle of Least Privilege. Never give more permissions than necessary.
RBAC Components
1. Roles and ClusterRoles
A Role defines what actions can be performed on which resources.
Role (namespace-scoped):
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: pod-reader
namespace: default
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]ClusterRole (cluster-wide):
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: pod-reader
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]2. RoleBindings and ClusterRoleBindings
A binding connects a Role to users/service accounts.
RoleBinding (namespace-scoped):
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: read-pods
namespace: default
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: pod-reader
subjects:
- kind: User
name: [email protected]
apiGroup: rbac.authorization.k8s.io
- kind: Group
name: developers
apiGroup: rbac.authorization.k8s.ioClusterRoleBinding:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: read-pods-global
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: pod-reader
subjects:
- kind: User
name: [email protected]
apiGroup: rbac.authorization.k8s.ioHow RBAC Works
When a user makes a request to the Kubernetes API:
User makes request
│
▼
Is the user authenticated? (valid certificate, token, etc.)
│
├─ No → Reject (Unauthorized)
│
▼ Yes
Does the user's role allow this action?
│
├─ No → Reject (Forbidden)
│
▼ Yes
Is the action on an allowed resource?
│
├─ No → Reject (Forbidden)
│
▼ Yes
Execute the action ✓
Service Accounts
When applications (Pods) interact with the Kubernetes API, they use Service Accounts.
Default Service Account
Each namespace has a default service account:
kubectl get serviceaccounts
kubectl get serviceaccounts -n kube-systemOutput:
NAME SECRETS AGE
default 1 10d
Create a Service Account
kubectl create serviceaccount my-appOr via YAML:
apiVersion: v1
kind: ServiceAccount
metadata:
name: my-app-sa
namespace: defaultUse Service Account in Pod
apiVersion: v1
kind: Pod
metadata:
name: myapp
spec:
serviceAccountName: my-app-sa
containers:
- name: app
image: myapp:1.0The Pod automatically gets a token mounted at /var/run/secrets/kubernetes.io/serviceaccount/token
Pod Accessing the Kubernetes API
import requests
import os
# Read the token
with open('/var/run/secrets/kubernetes.io/serviceaccount/token', 'r') as f:
token = f.read()
# Read the CA certificate
ca_cert = '/var/run/secrets/kubernetes.io/serviceaccount/ca.crt'
# Get the API server address
api_server = os.environ['KUBERNETES_SERVICE_HOST']
api_port = os.environ['KUBERNETES_SERVICE_PORT']
# Make a request to the API
url = f'https://{api_server}:{api_port}/api/v1/pods'
headers = {'Authorization': f'Bearer {token}'}
response = requests.get(
url,
headers=headers,
verify=ca_cert # Use CA cert for HTTPS verification
)
print(response.json())Common RBAC Patterns
Pattern 1: Read-Only Access
Users can view resources but not modify them:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: viewer
rules:
- apiGroups: [""]
resources: ["pods", "pods/logs", "services"]
verbs: ["get", "list", "watch"]
- apiGroups: ["apps"]
resources: ["deployments", "statefulsets"]
verbs: ["get", "list", "watch"]Pattern 2: Namespace Admin
User can manage everything in one namespace but nothing else:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: namespace-admin
namespace: development
rules:
- apiGroups: [""]
resources: ["*"]
verbs: ["*"]
- apiGroups: ["apps"]
resources: ["*"]
verbs: ["*"]
- apiGroups: ["batch"]
resources: ["*"]
verbs: ["*"]Pattern 3: Deployment Manager
Users can create/update/delete Deployments but not touch Secrets:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: deployment-manager
namespace: default
rules:
- apiGroups: ["apps"]
resources: ["deployments", "replicasets", "statefulsets"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: [""]
resources: ["services"]
verbs: ["get", "list", "watch"]
# Cannot create or access SecretsPattern 4: Pod Exec (Debugging)
Developers can exec into Pods for debugging:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: pod-debugger
namespace: development
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list"]
- apiGroups: [""]
resources: ["pods/exec"]
verbs: ["create", "get"]Pattern 5: Secret Manager
Only specific people can access Secrets:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: secret-manager
namespace: production
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "list", "create", "update", "delete"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: secret-manager-binding
namespace: production
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: secret-manager
subjects:
- kind: Group
name: platform-team
apiGroup: rbac.authorization.k8s.ioPre-built Cluster Roles
Kubernetes comes with useful built-in roles:
kubectl get clusterroles | head -20Common built-in roles:
system:masters- Full cluster accessview- Read-only access to most resourcesedit- Read-write access to Deployments, Pods, Servicesadmin- Full admin access to a namespacecluster-admin- Full admin access to entire cluster
Using Built-in Roles
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: devs-can-edit
namespace: development
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: edit # Built-in edit role
subjects:
- kind: Group
name: developers
apiGroup: rbac.authorization.k8s.ioVerifying Permissions
Check Your Permissions
# What can I do?
kubectl auth can-i get pods
# yes
kubectl auth can-i delete secrets
# no
kubectl auth can-i create deployments --namespace=production
# noCheck Another User's Permissions
# What can [email protected] do?
kubectl auth can-i get pods [email protected]
kubectl auth can-i delete deployments [email protected]Check Specific Resources
# Can I get specific pod?
kubectl auth can-i get pods/my-podAPI Groups and Resources
When creating roles, you need to specify:
- apiGroups: Which API group (core, apps, batch, etc.)
- resources: Which resource types (pods, deployments, etc.)
- verbs: Which actions (get, list, create, delete, etc.)
Common API Groups and Resources
Core API (apiGroups: [""]):
- pods
- services
- secrets
- configmaps
- namespaces
Apps API (apiGroups: ["apps"]):
- deployments
- statefulsets
- daemonsets
- replicasets
Batch API (apiGroups: ["batch"]):
- jobs
- cronjobs
RBAC API (apiGroups: ["rbac.authorization.k8s.io"]):
- roles
- rolebindings
- clusterroles
- clusterrolebindings
Wildcard Usage
rules:
- apiGroups: ["*"] # All API groups
resources: ["*"] # All resources
verbs: ["*"] # All verbs
# This is effectively cluster-adminTesting RBAC
Test Setup
# Create test namespace
kubectl create namespace test-rbac
# Create restrictive service account
kubectl create serviceaccount limited-user -n test-rbac
# Give it minimal permissions
kubectl create role minimal-reader -n test-rbac --verb=get --resource=pods
kubectl create rolebinding minimal-reader-binding -n test-rbac \
--role=minimal-reader \
--serviceaccount=test-rbac:limited-userGet Service Account Token
# Get token
TOKEN=$(kubectl -n test-rbac create token limited-user --duration=1h)
echo $TOKEN
# Set as default auth
kubectl config set-credentials limited-user --token=$TOKEN
kubectl config set-context test-context --cluster=<cluster> --user=limited-user
kubectl config use-context test-context
# Now test what they can do
kubectl get pods # Should work
kubectl get pods -n default # Should fail (different namespace)
kubectl delete pod my-pod # Should fail (no delete permission)Audit Logging
Enable audit logging to track RBAC decisions:
# /etc/kubernetes/audit-policy.yaml
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: RequestResponse
omitStages:
- RequestReceived
resources:
- group: ""
resources: ["secrets"]
namespaces: ["production"]
- level: Metadata
omitStages:
- RequestReceived
verbs: ["create", "update", "patch", "delete"]
- level: Metadata
omitStages:
- RequestReceivedConfigure API server:
--audit-policy-file=/etc/kubernetes/audit-policy.yaml
--audit-log-path=/var/log/kubernetes/audit.log
--audit-log-maxage=7
--audit-log-maxbackup=10Security Best Practices
\u2705 Principle of Least Privilege
- Only grant minimum permissions needed
- Regularly review and revoke unnecessary permissions
\u2705 Use Service Accounts for Applications
- Never use default service account
- Create dedicated service accounts per application
\u2705 Namespace Isolation
- Use different service accounts per namespace
- Use Network Policies in addition to RBAC
\u2705 Audit RBAC Changes
- Log all role and binding changes
- Alert on suspicious permission grants
\u2705 Regular Permission Audits
- Review who has what permissions
- Remove accounts for departed team members
\u274c Don't Use cluster-admin
- Except for cluster administrators
- Most users should have namespace-level roles
\u274c Don't Put Passwords in Environment Variables
- Use Secrets RBAC to control access
- Audit who accesses Secrets
\u274c Don't Share Service Accounts
- Each application gets its own SA
- Makes audit and revocation easier