Stage 5 · Platform
Security, Identity & Admission
RBAC Design
Roles, ClusterRoles, aggregation labels, impersonation checks, and least-privilege reviews.
RBAC Model
RBAC maps subjects (users, groups, ServiceAccounts) to permissions (verbs on resources). Roles define permissions. RoleBindings assign Roles to subjects. ClusterRoles and ClusterRoleBindings provide cluster-wide permissions.
API Request
-> Authentication (who are you?)
-> Authorization (RBAC check)
-> Find all RoleBindings in the namespace
-> Find all ClusterRoleBindings
-> Check if any binding grants the requested permission
-> If granted: allow
-> If denied: 403 ForbiddenRBAC checks are additive — if any RoleBinding or ClusterRoleBinding grants the permission, it's allowed. There's no deny mechanism. To restrict access, simply don't grant the permission.
Role Design
Design Roles with least privilege: grant only the permissions needed. Use resourceNames to restrict to specific objects. Use namespace-scoped Roles instead of ClusterRoles when possible. Document the purpose of each Role.
# Developer role — read-only access
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: developer-read
namespace: production
rules:
- apiGroups: ["", "apps", "batch"]
resources: ["pods", "pods/log", "deployments", "services", "configmaps"]
verbs: ["get", "list", "watch"]
---
# SRE role — full management access
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: sre-admin
namespace: production
rules:
- apiGroups: ["", "apps", "batch", "networking.k8s.io"]
resources: ["*"]
verbs: ["*"]
---
# CI/CD role — deploy only specific resources
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: cicd-deployer
namespace: production
rules:
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "list", "patch", "update"]
resourceNames: ["api", "web", "worker"]
- apiGroups: [""]
resources: ["configmaps", "secrets"]
verbs: ["get", "list"]
resourceNames: ["app-config", "db-credentials"]Developer role provides read-only access. SRE role provides full management. CI/CD role is scoped to specific deployments and config resources. resourceNames prevents access to other resources.
ClusterRoles
ClusterRoles provide cluster-wide permissions. Use them for: cluster-level resources (nodes, PVs, StorageClasses), monitoring (reading across namespaces), and platform tools (Prometheus, cert-manager).
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: monitoring-reader
rules:
- apiGroups: [""]
resources: ["nodes", "services", "endpoints", "pods"]
verbs: ["get", "list", "watch"]
- apiGroups: ["apps"]
resources: ["deployments", "statefulsets", "daemonsets"]
verbs: ["get", "list", "watch"]
- apiGroups: ["metrics.k8s.io"]
resources: ["nodes", "pods"]
verbs: ["get", "list"]
- nonResourceURLs: ["/metrics", "/healthz"]
verbs: ["get"]ClusterRoles grant access to cluster-scoped resources and non-resource URLs. monitoring-reader can read nodes, pods, and services across all namespaces. nonResourceURLs grants access to /metrics and /healthz.
Role Aggregation
Aggregated ClusterRoles merge multiple roles using labels. Add a label to your ClusterRole, and it's automatically included in any aggregated role with the same label. This is useful for extending built-in roles with CRD permissions.
# Base monitoring role
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: monitoring-endpoints
labels:
rbac.example.com/aggregate-to-monitoring: "true"
rules:
- apiGroups: [""]
resources: ["services", "endpoints", "pods"]
verbs: ["get", "list", "watch"]
---
# Additional Prometheus CRD permissions
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: monitoring-prometheus
labels:
rbac.example.com/aggregate-to-monitoring: "true"
rules:
- apiGroups: ["monitoring.coreos.com"]
resources: ["servicemonitors", "prometheusrules"]
verbs: ["get", "list", "watch"]
---
# Aggregated role — includes all roles with the label
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: monitoring-full
aggregationRule:
clusterRoleSelectors:
- matchLabels:
rbac.example.com/aggregate-to-monitoring: "true"
rules: []monitoring-full automatically includes all ClusterRoles with the aggregation label. When you add a new CRD for monitoring, just add a ClusterRole with the label — no need to modify the aggregated role.
Impersonation
Impersonation lets you test RBAC by acting as another user. kubectl auth can-i --as=username checks permissions. This is essential for verifying least-privilege before granting access.
# Check permissions for a user
kubectl auth can-i get pods --as=developer@example.com -n production
# Check all permissions for a ServiceAccount
kubectl auth can-i --list --as=system:serviceaccount:production:api-service
# Check cluster-wide permissions
kubectl auth can-i get nodes --as=developer@example.com
# Test if a user can create pods
kubectl auth can-i create pods --as=developer@example.com -n production
# Check what a user CAN'T do
kubectl auth can-i '*' '*' --as=developer@example.com -n productionimpersonation is read-only — it doesn't perform actions. It checks if the user WOULD have permission. Use this to verify RBAC before granting access. The --as flag specifies the user to impersonate.
Least-Privilege Review
Regularly review RBAC permissions to ensure least-privilege. Remove unused RoleBindings, check for over-permissive roles, and verify ServiceAccount permissions. Use tools like kubectl-who-can and rakkess for analysis.
# kubectl-who-can — who has access to what
kubectl who-can get pods -n production
kubectl who-can create deployments -n production
# rakkess — effective permissions
rakkess --subject developer@example.com -n production
# List all ClusterRoleBindings
kubectl get clusterrolebindings -o json | jq '.items[] | select(.subjects[]?.name=="developer@example.com")'
# Check for over-permissive roles
kubectl get clusterrole -o json | jq '.items[] | select(.rules[]?.verbs[]=="*") | .metadata.name'kubectl-who-can shows who has a specific permission. rakkess shows all permissions for a user. Check for wildcard verbs (verbs: ['*']) and wildcard resources (resources: ['*']) — these are over-permissive.
Review RBAC monthly. Check: ServiceAccount permissions, over-permissive roles, unused RoleBindings, and system:members group access. Use kubectl auth can-i --list to audit each ServiceAccount's effective permissions.
Mark this lesson complete to store local progress and unlock a cleaner resume path the next time you visit.