Skip to content

Kubernetes RBAC (Role-Based Access Control)

RBAC regulates access to Kubernetes resources based on roles assigned to users.

RBAC Overview

┌──────────────────────────────────────────────────┐
│              RBAC Components                     │
├──────────────────────────────────────────────────┤
│                                                  │
│  Subject  ──────►  RoleBinding  ──────►  Role   │
│  (Who)            (Assignment)         (What)   │
│                                                  │
│  • User                                          │
│  • Group                                         │
│  • ServiceAccount                                │
└──────────────────────────────────────────────────┘

Core Concepts

Subjects (Who)

  • User: Human users
  • Group: Collection of users
  • ServiceAccount: Pod identity

Resources (What)

  • Pods, Services, Deployments, etc.
  • API groups and versions
  • Specific resource names

Verbs (Actions)

  • get, list, watch
  • create, update, patch, delete
  • deletecollection

Role vs ClusterRole

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"]

RoleBinding vs ClusterRoleBinding

RoleBinding

Grants permissions within a namespace:

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: read-pods
  namespace: default
subjects:
- kind: User
  name: jane
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

ClusterRoleBinding

Grants cluster-wide permissions:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: read-pods-global
subjects:
- kind: User
  name: jane
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

Common Role Examples

Read-Only Access

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: read-only
  namespace: default
rules:
- apiGroups: ["", "apps", "batch"]
  resources:
  - pods
  - deployments
  - services
  - jobs
  - cronjobs
  verbs: ["get", "list", "watch"]

Developer Role

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: developer
  namespace: development
rules:
# Pods
- apiGroups: [""]
  resources: ["pods", "pods/log"]
  verbs: ["get", "list", "watch", "create", "delete"]
- apiGroups: [""]
  resources: ["pods/exec"]
  verbs: ["create"]

# Deployments
- apiGroups: ["apps"]
  resources: ["deployments", "replicasets"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]

# Services
- apiGroups: [""]
  resources: ["services"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]

# ConfigMaps and Secrets
- apiGroups: [""]
  resources: ["configmaps"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: [""]
  resources: ["secrets"]
  verbs: ["get", "list"]

Admin Role

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: namespace-admin
  namespace: production
rules:
- apiGroups: ["*"]
  resources: ["*"]
  verbs: ["*"]

CI/CD Role

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: cicd-deployer
  namespace: production
rules:
# Deployments
- apiGroups: ["apps"]
  resources: ["deployments"]
  verbs: ["get", "list", "create", "update", "patch"]

# Pods (for logs)
- apiGroups: [""]
  resources: ["pods", "pods/log"]
  verbs: ["get", "list"]

# Services
- apiGroups: [""]
  resources: ["services"]
  verbs: ["get", "list", "create", "update"]

# ConfigMaps
- apiGroups: [""]
  resources: ["configmaps"]
  verbs: ["get", "list", "create", "update"]

ServiceAccount

Create ServiceAccount

apiVersion: v1
kind: ServiceAccount
metadata:
  name: app-sa
  namespace: default

Use ServiceAccount in Pod

apiVersion: v1
kind: Pod
metadata:
  name: app-pod
spec:
  serviceAccountName: app-sa
  containers:
  - name: app
    image: myapp:1.0

ServiceAccount with Role

apiVersion: v1
kind: ServiceAccount
metadata:
  name: pod-reader-sa
  namespace: default
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: pod-reader
  namespace: default
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: read-pods
  namespace: default
subjects:
- kind: ServiceAccount
  name: pod-reader-sa
  namespace: default
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

Resource Names

Restrict access to specific resources:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: specific-pod-reader
  namespace: default
rules:
- apiGroups: [""]
  resources: ["pods"]
  resourceNames: ["my-pod", "another-pod"]
  verbs: ["get", "delete"]

Aggregated ClusterRoles

Combine multiple ClusterRoles:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: monitoring
  labels:
    rbac.example.com/aggregate-to-monitoring: "true"
rules:
- apiGroups: [""]
  resources: ["pods", "nodes"]
  verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: monitoring-aggregate
aggregationRule:
  clusterRoleSelectors:
  - matchLabels:
      rbac.example.com/aggregate-to-monitoring: "true"
rules: []  # Automatically filled

Default ClusterRoles

Kubernetes provides default roles:

  • cluster-admin: Full cluster access
  • admin: Full namespace access
  • edit: Read/write namespace access
  • view: Read-only namespace access
# View default roles
kubectl get clusterroles

# Describe default role
kubectl describe clusterrole view

Using Default Roles

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: dev-view
  namespace: development
subjects:
- kind: User
  name: developer
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: view
  apiGroup: rbac.authorization.k8s.io

Multi-Namespace Access

Grant access to multiple namespaces:

# RoleBinding in namespace1
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: read-pods
  namespace: namespace1
subjects:
- kind: User
  name: jane
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io
---
# RoleBinding in namespace2
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: read-pods
  namespace: namespace2
subjects:
- kind: User
  name: jane
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

Group Bindings

Bind roles to groups:

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: developers
  namespace: development
subjects:
- kind: Group
  name: developers
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: developer
  apiGroup: rbac.authorization.k8s.io

Testing RBAC

Check Permissions

# Check if you can perform action
kubectl auth can-i create deployments

# Check for specific namespace
kubectl auth can-i create deployments --namespace=production

# Check as another user
kubectl auth can-i create deployments --as=jane

# Check as service account
kubectl auth can-i create deployments \
  --as=system:serviceaccount:default:app-sa

# List all permissions
kubectl auth can-i --list

# List permissions in namespace
kubectl auth can-i --list --namespace=production

Impersonate User

# Run command as user
kubectl get pods --as=jane

# Run as service account
kubectl get pods --as=system:serviceaccount:default:app-sa

# Run as group
kubectl get pods --as=jane --as-group=developers

RBAC Commands

# List roles
kubectl get roles
kubectl get clusterroles

# List role bindings
kubectl get rolebindings
kubectl get clusterrolebindings

# Describe role
kubectl describe role pod-reader

# Describe role binding
kubectl describe rolebinding read-pods

# Create role
kubectl create role pod-reader --verb=get,list --resource=pods

# Create role binding
kubectl create rolebinding read-pods \
  --role=pod-reader \
  --user=jane

# Create cluster role
kubectl create clusterrole pod-reader --verb=get,list --resource=pods

# Create cluster role binding
kubectl create clusterrolebinding read-pods-global \
  --clusterrole=pod-reader \
  --user=jane

# Delete role
kubectl delete role pod-reader

# Delete role binding
kubectl delete rolebinding read-pods

Common Patterns

Read-Only User

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: readonly-user
subjects:
- kind: User
  name: readonly
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: view
  apiGroup: rbac.authorization.k8s.io

Namespace Admin

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: namespace-admin
  namespace: production
subjects:
- kind: User
  name: admin
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: admin
  apiGroup: rbac.authorization.k8s.io

CI/CD Pipeline

apiVersion: v1
kind: ServiceAccount
metadata:
  name: cicd-sa
  namespace: production
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: cicd-role
  namespace: production
rules:
- apiGroups: ["apps"]
  resources: ["deployments"]
  verbs: ["get", "list", "create", "update", "patch"]
- apiGroups: [""]
  resources: ["pods", "pods/log"]
  verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: cicd-binding
  namespace: production
subjects:
- kind: ServiceAccount
  name: cicd-sa
  namespace: production
roleRef:
  kind: Role
  name: cicd-role
  apiGroup: rbac.authorization.k8s.io

Best Practices

  1. Principle of Least Privilege
  2. Grant minimum required permissions
  3. Use specific verbs and resources
  4. Avoid wildcard permissions

  5. Use ServiceAccounts

  6. Don't use default service account
  7. Create dedicated service accounts
  8. One per application/component

  9. Namespace Isolation

  10. Use Roles instead of ClusterRoles
  11. Separate environments by namespace
  12. Limit cross-namespace access

  13. Regular Audits

  14. Review permissions regularly
  15. Remove unused roles
  16. Monitor RBAC changes

  17. Documentation

  18. Document role purposes
  19. Maintain role inventory
  20. Use descriptive names

  21. Testing

  22. Test permissions before applying
  23. Use kubectl auth can-i
  24. Verify in non-production first

Security Considerations

  1. Avoid cluster-admin
  2. Don't use for regular operations
  3. Create specific roles instead
  4. Use only for cluster management

  5. Restrict Secret Access

    rules:
    - apiGroups: [""]
      resources: ["secrets"]
      verbs: ["get"]
      resourceNames: ["specific-secret"]
    

  6. Limit Exec Access

    rules:
    - apiGroups: [""]
      resources: ["pods/exec"]
      verbs: ["create"]
      resourceNames: ["debug-pod"]
    

  7. Audit Logging

  8. Enable audit logs
  9. Monitor RBAC changes
  10. Alert on suspicious activity

Troubleshooting

# Check current user
kubectl auth whoami

# Check permissions
kubectl auth can-i create pods

# View role details
kubectl describe role pod-reader

# View binding details
kubectl describe rolebinding read-pods

# Check service account token
kubectl get secret -n default | grep app-sa

# View service account
kubectl describe sa app-sa

# Check pod service account
kubectl get pod pod-name -o jsonpath='{.spec.serviceAccountName}'

References