Asi implementing-kubernetes-pod-security-standards
Pod Security Standards (PSS) define three levels of security policies -- Privileged, Baseline, and Restricted -- enforced by the Pod Security Admission (PSA) controller built into Kubernetes 1.25+. PS
install
source · Clone the upstream repo
git clone https://github.com/plurigrid/asi
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/plurigrid/asi "$T" && mkdir -p ~/.claude/skills && cp -r "$T/plugins/asi/skills/implementing-kubernetes-pod-security-standards" ~/.claude/skills/plurigrid-asi-implementing-kubernetes-pod-security-standards && rm -rf "$T"
manifest:
plugins/asi/skills/implementing-kubernetes-pod-security-standards/SKILL.mdsource content
Implementing Kubernetes Pod Security Standards
Overview
Pod Security Standards (PSS) define three levels of security policies -- Privileged, Baseline, and Restricted -- enforced by the Pod Security Admission (PSA) controller built into Kubernetes 1.25+. PSA replaces the deprecated PodSecurityPolicy and provides namespace-level enforcement with three modes: enforce, audit, and warn.
When to Use
- When deploying or configuring implementing kubernetes pod security standards capabilities in your environment
- When establishing security controls aligned to compliance requirements
- When building or improving security architecture for this domain
- When conducting security assessments that require this implementation
Prerequisites
- Kubernetes cluster 1.25+ (PSA GA)
- kubectl configured with cluster-admin access
- Understanding of Linux capabilities and security contexts
Core Concepts
Three Security Profiles
| Profile | Purpose | Restrictions |
|---|---|---|
| Privileged | Unrestricted, system workloads | None |
| Baseline | Prevents known escalations | No hostNetwork, hostPID, hostIPC, privileged containers, dangerous capabilities |
| Restricted | Hardened best practices | Non-root, drop ALL caps, seccomp required, read-only rootfs recommended |
Three Enforcement Modes
| Mode | Behavior |
|---|---|
| enforce | Rejects pods that violate the policy |
| audit | Logs violations in audit log but allows pod |
| warn | Returns warning to user but allows pod |
Workflow
Step 1: Label Namespaces for PSA
# Restricted namespace - production workloads apiVersion: v1 kind: Namespace metadata: name: production labels: 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 pod-security.kubernetes.io/warn: restricted pod-security.kubernetes.io/warn-version: latest
# Baseline namespace - general workloads apiVersion: v1 kind: Namespace metadata: name: staging labels: pod-security.kubernetes.io/enforce: baseline pod-security.kubernetes.io/enforce-version: latest pod-security.kubernetes.io/audit: restricted pod-security.kubernetes.io/audit-version: latest pod-security.kubernetes.io/warn: restricted pod-security.kubernetes.io/warn-version: latest
# Privileged namespace - system components only apiVersion: v1 kind: Namespace metadata: name: kube-system labels: pod-security.kubernetes.io/enforce: privileged pod-security.kubernetes.io/enforce-version: latest
Step 2: Apply Labels to Existing Namespaces
# Apply restricted enforcement to production kubectl label namespace production \ pod-security.kubernetes.io/enforce=restricted \ pod-security.kubernetes.io/audit=restricted \ pod-security.kubernetes.io/warn=restricted \ --overwrite # Apply baseline to staging with restricted warnings kubectl label namespace staging \ pod-security.kubernetes.io/enforce=baseline \ pod-security.kubernetes.io/audit=restricted \ pod-security.kubernetes.io/warn=restricted \ --overwrite # Check labels on all namespaces kubectl get namespaces -L pod-security.kubernetes.io/enforce
Step 3: Create Compliant Pod Specs
# Restricted-compliant deployment apiVersion: apps/v1 kind: Deployment metadata: name: secure-app namespace: production spec: replicas: 3 selector: matchLabels: app: secure-app template: metadata: labels: app: secure-app spec: automountServiceAccountToken: false securityContext: runAsNonRoot: true runAsUser: 65534 runAsGroup: 65534 fsGroup: 65534 seccompProfile: type: RuntimeDefault containers: - name: app image: myregistry.com/myapp:v1.0.0@sha256:abc123 ports: - containerPort: 8080 protocol: TCP securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: drop: - ALL runAsNonRoot: true runAsUser: 65534 resources: requests: memory: "64Mi" cpu: "100m" limits: memory: "256Mi" cpu: "500m" volumeMounts: - name: tmp mountPath: /tmp - name: cache mountPath: /var/cache volumes: - name: tmp emptyDir: sizeLimit: 100Mi - name: cache emptyDir: sizeLimit: 50Mi
Step 4: Gradual Migration Strategy
# Phase 1: Audit mode - discover violations without blocking kubectl label namespace my-namespace \ pod-security.kubernetes.io/audit=restricted \ pod-security.kubernetes.io/warn=restricted # Check audit logs for violations kubectl logs -n kube-system -l component=kube-apiserver | grep "pod-security" # Phase 2: Enforce baseline, warn on restricted kubectl label namespace my-namespace \ pod-security.kubernetes.io/enforce=baseline \ pod-security.kubernetes.io/warn=restricted \ --overwrite # Phase 3: Full restricted enforcement kubectl label namespace my-namespace \ pod-security.kubernetes.io/enforce=restricted \ --overwrite
Step 5: Dry-Run Enforcement Testing
# Test what would happen with restricted enforcement kubectl label --dry-run=server --overwrite namespace my-namespace \ pod-security.kubernetes.io/enforce=restricted # Example output: # Warning: existing pods in namespace "my-namespace" violate the new # PodSecurity enforce level "restricted:latest" # Warning: nginx-xxx: allowPrivilegeEscalation != false, # unrestricted capabilities, runAsNonRoot != true, seccompProfile
Baseline Profile Restrictions
| Control | Restricted | Requirement |
|---|---|---|
| HostProcess | Must not set | Pods cannot use Windows HostProcess |
| Host Namespaces | Must not set | No hostNetwork, hostPID, hostIPC |
| Privileged | Must not set | No privileged: true |
| Capabilities | Baseline list only | Only NET_BIND_SERVICE, drop ALL for restricted |
| HostPath Volumes | Must not use | No hostPath volume mounts |
| Host Ports | Must not use | No hostPort in container spec |
| AppArmor | Default/runtime | Cannot set to unconfined |
| SELinux | Limited types | Only container_t, container_init_t, container_kvm_t |
| /proc Mount Type | Default only | Must use Default proc mount |
| Seccomp | RuntimeDefault or Localhost | Must specify seccomp profile (restricted) |
| Sysctls | Safe set only | Limited to safe sysctls |
Validation Commands
# Verify namespace labels kubectl get ns --show-labels | grep pod-security # Test pod creation against policy kubectl run test-pod --image=nginx --namespace=production --dry-run=server # Check for violations in audit logs kubectl get events --field-selector reason=FailedCreate -A # Scan with Kubescape for PSS compliance kubescape scan framework nsa --namespace production