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:

MethodUsed By
X.509 client certificatesCluster admins, kubelets
Bearer tokensService accounts, OIDC
OIDC (OpenID Connect)Human users (Google, Okta, etc.)
Webhook tokensCustom auth systems

Service Accounts (for Pods)

yaml
apiVersion: 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

ObjectScopePurpose
RoleNamespaceDefines permissions within a namespace
ClusterRoleCluster-wideDefines permissions across all namespaces
RoleBindingNamespaceGrants Role to users in a namespace
ClusterRoleBindingCluster-wideGrants ClusterRole cluster-wide

Role (Namespace-Scoped)

yaml
apiVersion: 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)

yaml
apiVersion: 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

yaml
apiVersion: 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

yaml
apiVersion: 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

VerbHTTP MethodDescription
getGET (single)Read one resource
listGET (collection)List resources
watchGET (streaming)Watch for changes
createPOSTCreate resource
updatePUTFull update
patchPATCHPartial update
deleteDELETEDelete resource
deletecollectionDELETEDelete multiple

Built-in ClusterRoles

RolePermissions
cluster-adminFull access to everything
adminFull access within a namespace
editRead/write most resources in namespace
viewRead-only access to namespace

Pod Security

Pod Security Standards (PSS)

Three levels of security policies:

LevelDescription
PrivilegedUnrestricted (no restrictions)
BaselineMinimally restrictive (blocks known privilege escalation)
RestrictedHeavily 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)

yaml
spec: 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

ControllerPurpose
NamespaceLifecyclePrevent changes in terminating namespaces
LimitRangerEnforce resource limits
ResourceQuotaEnforce namespace quotas
PodSecurityEnforce pod security standards
MutatingAdmissionWebhookCall external webhooks to modify resources
ValidatingAdmissionWebhookCall external webhooks to validate resources

Resource Quotas

yaml
apiVersion: 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

yaml
apiVersion: 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:

ToolDescription
OPA/GatekeeperGeneral-purpose policy engine (Rego language)
KyvernoKubernetes-native policies (YAML)
KubewardenWebAssembly-based policies

Kyverno Example

yaml
apiVersion: 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:

  1. "Explain RBAC in Kubernetes"
  2. "How do you secure a multi-tenant cluster?"
  3. "What are admission controllers?"
  4. "How would you restrict what containers can do?"
  5. "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

Official Links