Namespace & RBAC Isolation
Apply different Pod Security Standard levels to dev, staging, and production namespaces. Create a service account scoped to the dev namespace and prove that a compromised dev account cannot list pods in production.
PSA Levels per Environment
Different Security Levels for Different Environments
Production workloads need strict controls. Development needs flexibility so engineers aren't blocked by warnings every minute. Apply different PSA levels per namespace to match each environment's risk profile.
Create the environment namespaces
kubectl create namespace dev
kubectl create namespace staging
kubectl create namespace production
Apply different PSA levels
# dev: warn only — pods run but developers see warnings
kubectl label namespace dev \
pod-security.kubernetes.io/warn=baseline \
pod-security.kubernetes.io/warn-version=latest
# staging: enforce baseline — blocks known privilege escalations
kubectl label namespace staging \
pod-security.kubernetes.io/enforce=baseline \
pod-security.kubernetes.io/enforce-version=latest
# production: enforce restricted — strictest standard
kubectl label namespace production \
pod-security.kubernetes.io/enforce=restricted \
pod-security.kubernetes.io/enforce-version=latest \
pod-security.kubernetes.io/audit=restricted \
pod-security.kubernetes.io/audit-version=latest
Test the same root-user pod across all three namespaces
cat > test-pod.yaml << 'EOF'
apiVersion: v1
kind: Pod
metadata:
name: test-pod
spec:
containers:
- name: app
image: public.ecr.aws/docker/library/busybox:1.36
command: ["sleep", "3600"]
securityContext:
runAsUser: 0
privileged: false
EOF
kubectl apply -f test-pod.yaml -n dev && echo "dev: allowed (with warning)"
kubectl apply -f test-pod.yaml -n staging && echo "staging: allowed"
kubectl apply -f test-pod.yaml -n production 2>&1 | head -3
Expected:
dev: allowed (with warning)
staging: allowed
Error from server (Forbidden): violates PodSecurity "restricted:latest" ...
RBAC Namespace Scoping
A Compromised Dev Account Cannot Reach Production
Namespaces alone are not a security boundary. Combine them with RBAC and a compromised service account in dev cannot list pods in production.
Create a developer service account
kubectl create serviceaccount dev-user -n dev
cat > dev-role.yaml << 'EOF'
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: dev-access
namespace: dev
rules:
- apiGroups: [""]
resources: ["pods", "services", "configmaps"]
verbs: ["get", "list", "watch", "create", "update", "delete"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: dev-access-binding
namespace: dev
subjects:
- kind: ServiceAccount
name: dev-user
namespace: dev
roleRef:
kind: Role
apiGroup: rbac.authorization.k8s.io
name: dev-access
EOF
kubectl apply -f dev-role.yaml
Verify namespace isolation
kubectl auth can-i list pods -n dev --as=system:serviceaccount:dev:dev-user
kubectl auth can-i list pods -n production --as=system:serviceaccount:dev:dev-user
Expected: yes / no
Cleanup
kubectl delete namespace dev staging production
- Previous lesson
- Pod Hardening & Pod Security Admission
- Next lesson
- Kubernetes Network Policy