18 - RBAC & Security
Kubernetes Security Layers
1. Transport Security → TLS everywhere
2. Authentication → Who are you?
3. Authorization (RBAC) → What can you do?
4. Admission Control → Should this be allowed?
5. Pod Security → How restricted are pods?
6. Network Policies → Who can talk to whom?
7. Secret Management → How are secrets protected?
Authentication (AuthN)
"Who are you?" -- K8s doesn't have a user database. It relies on external identity:
| Method | Used By |
|---|---|
| X.509 client certificates | Cluster admins, kubelets |
| Bearer tokens | Service accounts, OIDC |
| OIDC (OpenID Connect) | Human users (Google, Okta, etc.) |
| Webhook tokens | Custom auth systems |
Service Accounts (for Pods)
yamlapiVersion: v1 kind: ServiceAccount metadata: name: api-sa namespace: default annotations: # AWS: IAM role for service account (IRSA) eks.amazonaws.com/role-arn: arn:aws:iam::123456:role/api-role
yaml# Use in a Pod spec: serviceAccountName: api-sa automountServiceAccountToken: false # Disable if not needed
RBAC (Role-Based Access Control)
RBAC controls what authenticated users/service accounts can do.
Four RBAC Objects
| Object | Scope | Purpose |
|---|---|---|
| Role | Namespace | Defines permissions within a namespace |
| ClusterRole | Cluster-wide | Defines permissions across all namespaces |
| RoleBinding | Namespace | Grants Role to users in a namespace |
| ClusterRoleBinding | Cluster-wide | Grants ClusterRole cluster-wide |
Role (Namespace-Scoped)
yamlapiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: pod-reader namespace: production rules: - apiGroups: [""] # "" = core API group resources: ["pods"] verbs: ["get", "list", "watch"] - apiGroups: [""] resources: ["pods/log"] verbs: ["get"] - apiGroups: ["apps"] resources: ["deployments"] verbs: ["get", "list"]
ClusterRole (Cluster-Scoped)
yamlapiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: secret-reader rules: - apiGroups: [""] resources: ["secrets"] verbs: ["get", "list"] - apiGroups: [""] resources: ["namespaces"] verbs: ["get", "list"] # Non-resource URLs (e.g., /healthz) - nonResourceURLs: ["/healthz", "/metrics"] verbs: ["get"]
RoleBinding
yamlapiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: read-pods namespace: production subjects: # Human user - kind: User name: alice@example.com apiGroup: rbac.authorization.k8s.io # Service account - kind: ServiceAccount name: api-sa namespace: default # Group - kind: Group name: developers apiGroup: rbac.authorization.k8s.io roleRef: kind: Role name: pod-reader apiGroup: rbac.authorization.k8s.io
ClusterRoleBinding
yamlapiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: cluster-admin-binding subjects: - kind: User name: admin@example.com apiGroup: rbac.authorization.k8s.io roleRef: kind: ClusterRole name: cluster-admin # Built-in super admin role apiGroup: rbac.authorization.k8s.io
Common Verbs
| Verb | HTTP Method | Description |
|---|---|---|
get | GET (single) | Read one resource |
list | GET (collection) | List resources |
watch | GET (streaming) | Watch for changes |
create | POST | Create resource |
update | PUT | Full update |
patch | PATCH | Partial update |
delete | DELETE | Delete resource |
deletecollection | DELETE | Delete multiple |
Built-in ClusterRoles
| Role | Permissions |
|---|---|
cluster-admin | Full access to everything |
admin | Full access within a namespace |
edit | Read/write most resources in namespace |
view | Read-only access to namespace |
Pod Security
Pod Security Standards (PSS)
Three levels of security policies:
| Level | Description |
|---|---|
| Privileged | Unrestricted (no restrictions) |
| Baseline | Minimally restrictive (blocks known privilege escalation) |
| Restricted | Heavily restricted (hardened best practices) |
Pod Security Admission (PSA)
yaml# Apply security standards at namespace level apiVersion: v1 kind: Namespace metadata: name: production labels: # Enforce = reject non-compliant pods pod-security.kubernetes.io/enforce: restricted pod-security.kubernetes.io/enforce-version: latest # Warn = allow but warn pod-security.kubernetes.io/warn: restricted # Audit = log to audit log pod-security.kubernetes.io/audit: restricted
Security Context (Pod Level)
yamlspec: securityContext: runAsNonRoot: true runAsUser: 1001 runAsGroup: 1001 fsGroup: 1001 seccompProfile: type: RuntimeDefault containers: - name: app securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: drop: ["ALL"] # add: ["NET_BIND_SERVICE"] # Only if needed
Admission Controllers
Intercept API requests after authentication/authorization:
Request → AuthN → AuthZ (RBAC) → Admission Controllers → etcd
│
├─ Mutating (modify request)
│ └─ Add sidecar, default limits
│
└─ Validating (accept/reject)
└─ Check policies, enforce rules
Key Built-in Admission Controllers
| Controller | Purpose |
|---|---|
NamespaceLifecycle | Prevent changes in terminating namespaces |
LimitRanger | Enforce resource limits |
ResourceQuota | Enforce namespace quotas |
PodSecurity | Enforce pod security standards |
MutatingAdmissionWebhook | Call external webhooks to modify resources |
ValidatingAdmissionWebhook | Call external webhooks to validate resources |
Resource Quotas
yamlapiVersion: v1 kind: ResourceQuota metadata: name: team-quota namespace: team-a spec: hard: pods: "20" requests.cpu: "10" requests.memory: "20Gi" limits.cpu: "20" limits.memory: "40Gi" persistentvolumeclaims: "10" services.loadbalancers: "2"
Limit Ranges
yamlapiVersion: v1 kind: LimitRange metadata: name: default-limits namespace: team-a spec: limits: - type: Container default: # Default limits if not specified cpu: "500m" memory: "256Mi" defaultRequest: # Default requests if not specified cpu: "100m" memory: "128Mi" max: # Maximum allowed cpu: "2" memory: "2Gi" min: # Minimum required cpu: "50m" memory: "64Mi"
Policy Engines
For more advanced policies beyond PSA:
| Tool | Description |
|---|---|
| OPA/Gatekeeper | General-purpose policy engine (Rego language) |
| Kyverno | Kubernetes-native policies (YAML) |
| Kubewarden | WebAssembly-based policies |
Kyverno Example
yamlapiVersion: kyverno.io/v1 kind: ClusterPolicy metadata: name: require-labels spec: validationFailureAction: Enforce rules: - name: check-team-label match: any: - resources: kinds: ["Deployment"] validate: message: "Deployments must have a 'team' label" pattern: metadata: labels: team: "?*"
Audit Logging
Track who did what:
yaml# Audit policy apiVersion: audit.k8s.io/v1 kind: Policy rules: - level: Metadata resources: - group: "" resources: ["secrets"] - level: RequestResponse resources: - group: "" resources: ["pods"] verbs: ["create", "delete"]
kubectl Security Commands
bash# RBAC kubectl get roles,rolebindings -n production kubectl get clusterroles,clusterrolebindings kubectl describe role pod-reader -n production # Check permissions kubectl auth can-i create pods kubectl auth can-i delete deployments --as alice@example.com kubectl auth can-i '*' '*' # Am I cluster-admin? # Check what a service account can do kubectl auth can-i --list --as system:serviceaccount:default:api-sa # Resource quotas kubectl get resourcequota -n team-a kubectl describe resourcequota team-quota -n team-a
Security Checklist
- RBAC enabled and least-privilege roles defined
- Pod Security Admission enforced (restricted level)
- No pods running as root
- No privileged containers
- Network Policies restrict pod-to-pod traffic
- Secrets encrypted at rest
- Service accounts have minimal permissions
- automountServiceAccountToken: false where not needed
- Resource quotas and limit ranges set
- Audit logging enabled
- Image scanning in CI/CD pipeline
- Regular RBAC audits
FAANG Interview Angle
Common questions:
- "Explain RBAC in Kubernetes"
- "How do you secure a multi-tenant cluster?"
- "What are admission controllers?"
- "How would you restrict what containers can do?"
- "What's the principle of least privilege in K8s?"
Key answers:
- RBAC: Roles define permissions, RoleBindings assign them to users/SAs
- Multi-tenant: namespaces + RBAC + network policies + resource quotas + PSA
- Admission controllers intercept requests; mutating (modify) and validating (accept/reject)
- Pod Security Standards + SecurityContext: non-root, read-only fs, drop capabilities
- Minimal service account permissions, namespace-scoped roles, no cluster-admin for apps