Advanced Lesson 10 of 14

Security & RBAC

Secure your cluster with Role-Based Access Control, service accounts, network policies, and pod security.

🧒 Simple Explanation (ELI5)

Imagine a building with many rooms. RBAC is the keycard system: you get a keycard (Role) that opens only the rooms you need. An intern's card opens the lobby; a manager's opens the executive floor. Service Accounts are keycards for automated systems (elevators, HVAC) — they only have access to what they need to function. Network Policies are the walls and doors themselves — controlling who can even walk to which rooms.

🔧 Technical Explanation

RBAC Components

ResourceScopePurpose
RoleNamespaceDefines permissions (verbs on resources) within a namespace
ClusterRoleCluster-wideDefines permissions across all namespaces or for cluster-scoped resources
RoleBindingNamespaceBinds a Role/ClusterRole to a user/group/service account in a namespace
ClusterRoleBindingCluster-wideBinds a ClusterRole to a user/group/service account cluster-wide

API Request Flow

Every API request goes through: Authentication (who are you?) → Authorization (are you allowed?) → Admission Control (any last checks?) → Execute.

📊 Visual: RBAC Model

RBAC Binding Model
WHO (Subjects)
User: alice
Group: dev-team
ServiceAccount: deploy-bot
← binds →
RoleBinding
dev-role-binding
← references →
WHAT (Role)
get, list pods
create deployments
namespace: dev

⌨️ Hands-on

Create a Role and RoleBinding

yaml
# role.yaml - Read-only access to pods in "dev" namespace
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: pod-reader
  namespace: dev
rules:
  - apiGroups: [""]
    resources: ["pods", "pods/log"]
    verbs: ["get", "list", "watch"]
  - apiGroups: [""]
    resources: ["services"]
    verbs: ["get", "list"]
yaml
# rolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: read-pods
  namespace: dev
subjects:
  - kind: User
    name: alice
    apiGroup: rbac.authorization.k8s.io
  - kind: ServiceAccount
    name: monitoring-sa
    namespace: dev
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

Service Accounts

yaml
# serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: deploy-bot
  namespace: production
---
# Give it permission to manage deployments
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: deployment-manager
  namespace: production
rules:
  - apiGroups: ["apps"]
    resources: ["deployments"]
    verbs: ["get", "list", "create", "update", "patch"]
  - apiGroups: [""]
    resources: ["pods"]
    verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: deploy-bot-binding
  namespace: production
subjects:
  - kind: ServiceAccount
    name: deploy-bot
    namespace: production
roleRef:
  kind: Role
  name: deployment-manager
  apiGroup: rbac.authorization.k8s.io

Use Service Account in a Pod

yaml
apiVersion: v1
kind: Pod
metadata:
  name: deploy-bot-pod
  namespace: production
spec:
  serviceAccountName: deploy-bot
  automountServiceAccountToken: true
  containers:
    - name: bot
      image: bitnami/kubectl:latest
      command: ["sleep", "3600"]

Network Policy

yaml
# network-policy.yaml - Only allow traffic from app pods to database
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: db-allow-app-only
  namespace: production
spec:
  podSelector:
    matchLabels:
      role: database
  policyTypes:
    - Ingress
  ingress:
    - from:
        - podSelector:
            matchLabels:
              role: app
      ports:
        - protocol: TCP
          port: 5432
bash
# Test RBAC permissions
kubectl auth can-i get pods --as=alice -n dev        # yes
kubectl auth can-i delete pods --as=alice -n dev     # no
kubectl auth can-i get pods --as=alice -n production # no

# Check what a service account can do
kubectl auth can-i --list --as=system:serviceaccount:production:deploy-bot -n production
⚠️
Security Best Practice

Principle of least privilege: Grant only the minimum permissions needed. Never use cluster-admin for applications. Don't bind ClusterRoles to ServiceAccounts unless absolutely necessary. Audit RBAC regularly.

🐛 Debugging Scenarios

Scenario 1: "Forbidden" / "Permission Denied"

bash
# Error: "User 'alice' cannot list pods in namespace 'production'"

# Debug: Check what permissions alice has
kubectl auth can-i --list --as=alice -n production

# Check existing RoleBindings in the namespace
kubectl get rolebindings -n production -o wide

# Check if there's a ClusterRoleBinding
kubectl get clusterrolebindings -o wide | grep alice

# Fix: Create appropriate RoleBinding
kubectl create rolebinding alice-pods \
  --role=pod-reader \
  --user=alice \
  -n production

Scenario 2: Pod Can't Access Kubernetes API

Symptom: Application in pod gets 403 when calling the K8s API.

Scenario 3: Network Policy Blocking Traffic

bash
# Check network policies in namespace
kubectl get networkpolicies -n production

# Describe to see rules
kubectl describe networkpolicy db-allow-app-only -n production

# Test connectivity
kubectl exec app-pod -- curl db-service:5432
# If blocked, check pod labels match the policy's ingress "from" selector

# Common issue: Default deny policy exists but no allow policy for your traffic
# Fix: Add matching labels or create appropriate allow policy

🎯 Interview Questions

Beginner

Q: What is RBAC in Kubernetes?

RBAC (Role-Based Access Control) is a method of regulating access to Kubernetes resources based on the roles assigned to users or service accounts. It uses four objects: Role (namespace permissions), ClusterRole (cluster-wide permissions), RoleBinding (assigns Role to subjects in a namespace), ClusterRoleBinding (assigns ClusterRole cluster-wide).

Q: What is a Service Account?

A Service Account provides an identity for pods to interact with the Kubernetes API. Each namespace has a "default" SA. When pods need to call the K8s API (e.g., a CI/CD tool managing deployments), they use a Service Account with appropriate RBAC permissions bound to it.

Q: What is the difference between Role and ClusterRole?

Role: Scoped to a specific namespace. Can only grant permissions within that namespace. ClusterRole: Cluster-wide. Can grant permissions across all namespaces or for cluster-scoped resources (nodes, PVs, namespaces themselves). A ClusterRole can be used with a RoleBinding to grant its permissions in a single namespace.

Q: What is a Network Policy?

A Network Policy controls traffic flow to/from pods at the IP/port level. By default, all pods can communicate with all other pods. Network Policies restrict this — e.g., "only app pods can talk to database pods on port 5432." Requires a CNI plugin that supports Network Policies (Calico, Cilium, Azure CNI).

Q: What does 'kubectl auth can-i' do?

It checks if a user or service account has permission to perform an action. kubectl auth can-i create deployments checks for the current user. kubectl auth can-i get pods --as=alice -n dev checks for another user. kubectl auth can-i --list shows all permissions. Essential for RBAC debugging.

Intermediate

Q: What is Pod Security Admission (PSA)?

PSA replaced PodSecurityPolicy (removed in K8s 1.25). It enforces pod security standards at the namespace level using labels. Three profiles: Privileged (unrestricted), Baseline (prevents known privilege escalations), Restricted (heavily restricted, follows hardening best practices). three modes: enforce, audit, warn.

Q: What is the principle of least privilege in K8s?

Grant the minimum permissions required. Don't use cluster-admin for apps. Use namespace-scoped Roles instead of ClusterRoles. Don't mount service account tokens unless needed (automountServiceAccountToken: false). Use specific resource names where possible. Run containers as non-root. Drop all capabilities and add only what's needed.

Q: How do you secure the Kubernetes API server?

1) Enable RBAC (default since 1.8). 2) Use strong authentication (certificates, OIDC, not basic auth). 3) Enable audit logging. 4) Restrict anonymous access. 5) Use admission controllers (OPA Gatekeeper, Kyverno) for policy enforcement. 6) Encrypt etcd at rest. 7) Rotate credentials regularly. 8) Use network policies to limit who can reach the API server.

Q: What is securityContext in a pod spec?

securityContext defines privilege and access control for pods/containers. Key settings: runAsNonRoot: true, runAsUser: 1000, readOnlyRootFilesystem: true, allowPrivilegeEscalation: false, capabilities: drop: [ALL]. Pod-level securityContext applies to all containers; container-level overrides per-container.

Q: What are admission controllers and why are they important?

Admission controllers intercept API requests after auth but before persistence. They can validate (reject bad requests) or mutate (modify requests). Built-in examples: LimitRanger, ResourceQuota, PodSecurity. External: OPA Gatekeeper, Kyverno — enforce custom policies like "all containers must have resource limits" or "no latest tag allowed".

Scenario-Based

Q: A developer needs to view logs and exec into pods in the 'staging' namespace but shouldn't be able to create or delete anything. How do you configure this?

Create a Role with specific verbs: verbs: ["get", "list", "watch"] on pods, pods/log; verbs: ["create"] on pods/exec (exec requires create verb on the subresource). Bind it to the developer via RoleBinding in the staging namespace. They can view and exec but can't create, update, or delete any resources.

Q: A CI/CD pipeline needs to deploy to production. How do you securely configure access?

1) Create a dedicated ServiceAccount in the production namespace. 2) Create a Role with only the needed permissions (create/update deployments, get pods). 3) Bind the Role to the SA. 4) Generate a token for the SA and store it securely in the CI/CD system (as a protected secret). 5) Never give cluster-admin. 6) Audit pipeline actions via K8s audit logs. 7) Use short-lived tokens (TokenRequest API) instead of long-lived ones.

Q: Someone accidentally gave a pod cluster-admin access. What's the risk and how do you fix it?

Risk: If the pod is compromised, the attacker has full cluster access — can read all secrets, create privileged pods, access other namespaces, and even destroy the cluster. Fix: 1) Remove the ClusterRoleBinding immediately. 2) Create a scoped Role with only needed permissions. 3) Audit if anything was exploited during the exposure. 4) Implement OPA/Kyverno policies to prevent cluster-admin bindings to ServiceAccounts. 5) Set up alerts for ClusterRoleBinding creation.

Q: Pods in namespace A can reach pods in namespace B, but you need to isolate them. How?

Create a default-deny NetworkPolicy in both namespaces: podSelector: {} with empty ingress/egress (denies all). Then create specific allow policies for legitimate traffic. For namespace A: allow ingress only from namespace A pods. For namespace B: same. Cross-namespace traffic requires explicit namespaceSelector in the NetworkPolicy. Requires a CNI that supports Network Policies (Calico, Cilium).

Q: How do you implement a "no container runs as root" policy cluster-wide?

Multiple layers: 1) Pod Security Admission: Label namespaces with pod-security.kubernetes.io/enforce: restricted. 2) OPA Gatekeeper/Kyverno: Create a policy that rejects pods without runAsNonRoot: true and runAsUser > 0. 3) Best practice in images: Use USER 1000 in Dockerfiles. 4) Audit existing pods: kubectl get pods -A -o json | jq '.items[] | select(.spec.securityContext.runAsNonRoot != true)'.

🌍 Real-World Use Case

A healthcare platform (HIPAA-compliant) implements defense-in-depth security:

📝 Summary

← Back to Kubernetes Course