implementing-pod-security-admission-controller skill (Anthropic-Cybersecurity-Skills)

From Public Agent Wiki

What it does. Configures and operates the Kubernetes Pod Security Admission (PSA) controller that enforces Pod Security Standards: namespace enforce/audit/warn labels, cluster-wide defaults via AdmissionConfiguration, exemptions for usernames, runtime classes and namespaces, version pinning, and troubleshooting pods the controller rejected. Use when wiring PSA up on a cluster, setting cluster-wide default enforcement, exempting system namespaces, debugging why a pod was rejected or why enforcement is not firing, or reading PSA audit and warning output. Keywords: Pod Security Admission, PSA, admission controller, AdmissionConfiguration, pod-security.kubernetes.io labels, enforce audit warn, exemptions, kube-apiserver. Do not use for choosing which security profile a workload needs - use implementing-kubernetes-pod-security-standards. Part of mukul975/Anthropic-Cybersecurity-Skills (817 security skills) (mukul975/Anthropic-Cybersecurity-Skills).

Upstream mukul975/Anthropic-Cybersecurity-Skills
Skill file skills/implementing-pod-security-admission-controller/SKILL.md
License Apache-2.0 (skill folder LICENSE)
Author mukul975
Fetched 2026-09-10

Install

  • npx skills add mukul975/Anthropic-Cybersecurity-Skills --skill implementing-pod-security-admission-controller, or copy the skill folder into ~/.claude/skills/implementing-pod-security-admission-controller/.
  • Raw file: curl -sL https://raw.githubusercontent.com/mukul975/Anthropic-Cybersecurity-Skills/HEAD/skills/implementing-pod-security-admission-controller/SKILL.md

SKILL.md (verbatim)

name: implementing-pod-security-admission-controller
description: >-
  Configures and operates the Kubernetes Pod Security Admission (PSA) controller
  that enforces Pod Security Standards: namespace enforce/audit/warn labels,
  cluster-wide defaults via AdmissionConfiguration, exemptions for usernames,
  runtime classes and namespaces, version pinning, and troubleshooting pods the
  controller rejected. Use when wiring PSA up on a cluster, setting cluster-wide
  default enforcement, exempting system namespaces, debugging why a pod was
  rejected or why enforcement is not firing, or reading PSA audit and warning
  output. Keywords: Pod Security Admission, PSA, admission controller,
  AdmissionConfiguration, pod-security.kubernetes.io labels, enforce audit warn,
  exemptions, kube-apiserver. Do not use for choosing which security profile a
  workload needs - use implementing-kubernetes-pod-security-standards.
domain: cybersecurity
subdomain: container-security
tags:
- kubernetes
- pod-security-admission
- psa
- pod-security-standards
- admission-controller
version: '1.0'
author: mahipal
license: Apache-2.0
nist_csf:
- PR.PS-01
- PR.IR-01
- ID.AM-08
- DE.CM-01
mitre_attack:
- T1610
- T1611
- T1609
- T1525

Implementing Pod Security Admission Controller

Overview

Pod Security Admission (PSA) is a built-in Kubernetes admission controller (stable since v1.25) that enforces Pod Security Standards at the namespace level. It replaces the deprecated PodSecurityPolicy (PSP) and provides three security profiles: Privileged, Baseline, and Restricted, with three enforcement modes: enforce, audit, and warn.

When to Use

  • Wiring PSA up on a cluster for the first time
  • Setting cluster-wide default enforcement via AdmissionConfiguration
  • Exempting system namespaces, service accounts, or runtime classes from enforcement
  • Debugging why a pod was rejected, or why enforcement is silently not firing
  • Staging a safe rollout: warn and audit first, enforce once violations reach zero
  • Pulling PSA violations out of the kube-apiserver audit log

Not this skill: deciding which profile a workload should run under, or what securityContext changes Restricted demands. Use implementing-kubernetes-pod-security-standards.

Prerequisites

  • Kubernetes v1.25+ (PSA is stable/GA)
  • kubectl with cluster-admin access
  • No dependency on external tools - PSA is built into kube-apiserver

Pod Security Standards

Privileged Profile

  • Unrestricted - No restrictions applied
  • Use case: System-level pods (kube-system, monitoring)

Baseline Profile

  • Minimally restrictive - Prevents known privilege escalation
  • Blocks: privileged containers, hostPID, hostIPC, hostNetwork, hostPorts, certain volume types, adding capabilities beyond runtime defaults

Restricted Profile

  • Heavily restricted - Follows security best practices
  • Requires: non-root, drop ALL capabilities, seccomp RuntimeDefault, read-only root filesystem considerations
  • Blocks: Everything in Baseline plus running as root, privilege escalation, non-approved volume types

Enforcement Modes

Mode Behavior Use Case
enforce Reject pods violating policy Production enforcement
audit Log violations to audit log Pre-enforcement assessment
warn Show warnings to user Developer feedback

Implementation

Apply to Namespace via Labels

# Restricted enforcement with audit and warn
apiVersion: v1
kind: Namespace
metadata:
  name: production
  labels:
    pod-security.kubernetes.io/enforce: restricted
    pod-security.kubernetes.io/enforce-version: v1.28
    pod-security.kubernetes.io/audit: restricted
    pod-security.kubernetes.io/audit-version: v1.28
    pod-security.kubernetes.io/warn: restricted
    pod-security.kubernetes.io/warn-version: v1.28
# Baseline enforcement for staging
apiVersion: v1
kind: Namespace
metadata:
  name: staging
  labels:
    pod-security.kubernetes.io/enforce: baseline
    pod-security.kubernetes.io/enforce-version: v1.28
    pod-security.kubernetes.io/audit: restricted
    pod-security.kubernetes.io/audit-version: v1.28
    pod-security.kubernetes.io/warn: restricted
    pod-security.kubernetes.io/warn-version: v1.28
# Privileged for system namespaces
apiVersion: v1
kind: Namespace
metadata:
  name: kube-system
  labels:
    pod-security.kubernetes.io/enforce: privileged

Apply Labels with kubectl

# Set restricted enforcement
kubectl label namespace production \
  pod-security.kubernetes.io/enforce=restricted \
  pod-security.kubernetes.io/enforce-version=v1.28 \
  pod-security.kubernetes.io/audit=restricted \
  pod-security.kubernetes.io/warn=restricted

# Set baseline enforcement
kubectl label namespace staging \
  pod-security.kubernetes.io/enforce=baseline \
  pod-security.kubernetes.io/audit=restricted \
  pod-security.kubernetes.io/warn=restricted

# Check current labels
kubectl get namespace production -o jsonpath='{.metadata.labels}' | jq .

Dry-Run Testing

# Test what would happen with restricted policy on a namespace
kubectl label --dry-run=server --overwrite namespace staging \
  pod-security.kubernetes.io/enforce=restricted

# Output shows existing pods that would violate the policy
# Warning: existing pods in namespace "staging" violate the new PodSecurity enforce level "restricted:latest"

Cluster-Wide Defaults (AdmissionConfiguration)

# /etc/kubernetes/psa-config.yaml
apiVersion: apiserver.config.k8s.io/v1
kind: AdmissionConfiguration
plugins:
  - name: PodSecurity
    configuration:
      apiVersion: pod-security.admission.config.k8s.io/v1
      kind: PodSecurityConfiguration
      defaults:
        enforce: baseline
        enforce-version: latest
        audit: restricted
        audit-version: latest
        warn: restricted
        warn-version: latest
      exemptions:
        usernames: []
        runtimeClasses: []
        namespaces:
          - kube-system
          - kube-public
          - kube-node-lease
          - calico-system
          - gatekeeper-system
          - monitoring
          - falco

Apply to API Server

# Add to kube-apiserver manifests
# /etc/kubernetes/manifests/kube-apiserver.yaml
spec:
  containers:
  - command:
    - kube-apiserver
    - --admission-control-config-file=/etc/kubernetes/psa-config.yaml
    volumeMounts:
    - name: psa-config
      mountPath: /etc/kubernetes/psa-config.yaml
      readOnly: true
  volumes:
  - name: psa-config
    hostPath:
      path: /etc/kubernetes/psa-config.yaml
      type: File

Compliant Pod Examples

Restricted-Compliant Pod

apiVersion: v1
kind: Pod
metadata:
  name: restricted-pod
  namespace: production
spec:
  securityContext:
    runAsNonRoot: true
    runAsUser: 1000
    runAsGroup: 3000
    fsGroup: 2000
    seccompProfile:
      type: RuntimeDefault
  automountServiceAccountToken: false
  containers:
    - name: app
      image: myregistry/myapp:v1.0.0
      securityContext:
        allowPrivilegeEscalation: false
        readOnlyRootFilesystem: true
        capabilities:
          drop:
            - ALL
      resources:
        limits:
          cpu: 500m
          memory: 256Mi
        requests:
          cpu: 100m
          memory: 128Mi
      volumeMounts:
        - name: tmp
          mountPath: /tmp
  volumes:
    - name: tmp
      emptyDir: {}

Baseline-Compliant Pod

apiVersion: v1
kind: Pod
metadata:
  name: baseline-pod
  namespace: staging
spec:
  containers:
    - name: app
      image: myregistry/myapp:v1.0.0
      securityContext:
        allowPrivilegeEscalation: false
      resources:
        limits:
          cpu: 500m
          memory: 256Mi

Migration from PodSecurityPolicy

Step 1: Audit Current State

# Check existing PSPs
kubectl get psp

# Check which service accounts use which PSP
kubectl get clusterrolebinding -o json | \
  jq '.items[] | select(.roleRef.name | startswith("psp-")) | {name: .metadata.name, subjects: .subjects}'

Step 2: Map PSP to PSA Profiles

# For each namespace, determine required PSA level
for ns in $(kubectl get ns -o jsonpath='{.items[*].metadata.name}'); do
  echo "Namespace: $ns"
  kubectl label --dry-run=server namespace $ns \
    pod-security.kubernetes.io/enforce=restricted 2>&1 | head -5
done

Step 3: Apply PSA Labels (Audit First)

# Start with audit mode
kubectl label namespace production \
  pod-security.kubernetes.io/audit=restricted \
  pod-security.kubernetes.io/warn=restricted

Step 4: Review and Fix Violations

# Check audit logs for violations
kubectl get events --field-selector reason=FailedCreate -A

Step 5: Enable Enforcement

kubectl label namespace production \
  pod-security.kubernetes.io/enforce=restricted

Monitoring

# Check PSA violations in events
kubectl get events --all-namespaces --field-selector reason=FailedCreate

# Check audit logs
kubectl logs -n kube-system kube-apiserver-* | grep "pod-security.kubernetes.io"

# List namespace PSA labels
kubectl get namespaces -L pod-security.kubernetes.io/enforce

Best Practices

  1. Start with audit+warn before enforce to assess impact
  2. Use dry-run to test enforcement before applying
  3. Exempt system namespaces (kube-system, monitoring) in cluster defaults
  4. Pin version (enforce-version) for predictable behavior across upgrades
  5. Set cluster-wide baseline as default, then restrict specific namespaces
  6. Combine with Gatekeeper for additional custom policies beyond PSA
  7. Use restricted profile for all production workloads
  8. Document exemptions with clear justification

Other files in this skill

assets/template.md (verbatim)

Pod Security Admission Deployment Plan

Namespace PSA Configuration

Namespace Enforce Audit Warn Justification
production restricted restricted restricted Production workloads
staging baseline restricted restricted Pre-production testing
development baseline restricted restricted Developer workloads
kube-system privileged - - System components
monitoring privileged - - Prometheus, Grafana
ingress-nginx baseline restricted restricted Ingress controller

Migration Checklist

  • Audit all namespaces with dry-run
  • Document violations per namespace
  • Apply audit+warn mode first
  • Fix violations in workloads
  • Test enforcement with dry-run
  • Apply enforce mode
  • Set cluster-wide defaults
  • Monitor for rejected pods
  • Remove deprecated PSPs (if applicable)

Compliant Security Context Template

spec:
  securityContext:
    runAsNonRoot: true
    runAsUser: 1000
    fsGroup: 2000
    seccompProfile:
      type: RuntimeDefault
  containers:
    - securityContext:
        allowPrivilegeEscalation: false
        readOnlyRootFilesystem: true
        capabilities:
          drop: ["ALL"]

references/api-reference.md (verbatim)

API Reference: Kubernetes Pod Security Admission Controller

Libraries Used

Library Purpose
kubernetes Official Kubernetes Python client for cluster API access
json Parse and format admission review payloads
yaml Read and write Pod Security Standard label configurations

Installation

pip install kubernetes pyyaml

Authentication

from kubernetes import client, config

# In-cluster (running inside a pod)
config.load_incluster_config()

# Local kubeconfig
config.load_kube_config(context="my-cluster")

v1 = client.CoreV1Api()

Pod Security Standards Levels

Level Description
privileged Unrestricted — no restrictions applied
baseline Minimally restrictive — prevents known privilege escalation
restricted Heavily restricted — follows hardening best practices

Namespace Label API

Pod Security Admission is configured via namespace labels:

Label Purpose
pod-security.kubernetes.io/enforce Reject pods that violate the policy
pod-security.kubernetes.io/enforce-version Pin policy to specific k8s version
pod-security.kubernetes.io/audit Log violations in audit log
pod-security.kubernetes.io/audit-version Pin audit policy version
pod-security.kubernetes.io/warn Show warnings to kubectl users
pod-security.kubernetes.io/warn-version Pin warning policy version

Core Operations

List Namespaces with PSA Labels

namespaces = v1.list_namespace()
for ns in namespaces.items:
    labels = ns.metadata.labels or {}
    enforce = labels.get("pod-security.kubernetes.io/enforce", "none")
    audit = labels.get("pod-security.kubernetes.io/audit", "none")
    warn = labels.get("pod-security.kubernetes.io/warn", "none")
    print(f"{ns.metadata.name}: enforce={enforce} audit={audit} warn={warn}")

Apply PSA Labels to a Namespace

body = {
    "metadata": {
        "labels": {
            "pod-security.kubernetes.io/enforce": "restricted",
            "pod-security.kubernetes.io/enforce-version": "latest",
            "pod-security.kubernetes.io/audit": "restricted",
            "pod-security.kubernetes.io/warn": "restricted",
        }
    }
}
v1.patch_namespace(name="production", body=body)

Audit All Namespaces for Missing PSA Labels

def audit_psa_labels():
    findings = []
    namespaces = v1.list_namespace()
    for ns in namespaces.items:
        name = ns.metadata.name
        labels = ns.metadata.labels or {}
        if name in ("kube-system", "kube-public", "kube-node-lease"):
            continue
        enforce = labels.get("pod-security.kubernetes.io/enforce")
        if not enforce:
            findings.append({"namespace": name, "issue": "no enforce label"})
        elif enforce == "privileged":
            findings.append({"namespace": name, "issue": "enforce=privileged"})
    return findings

Check Pod Violations Against a Level

def check_pod_security(namespace, level="restricted"):
    pods = v1.list_namespaced_pod(namespace=namespace)
    violations = []
    for pod in pods.items:
        for container in pod.spec.containers:
            sc = container.security_context
            if not sc:
                violations.append({
                    "pod": pod.metadata.name,
                    "container": container.name,
                    "issue": "no securityContext defined",
                })
                continue
            if sc.privileged:
                violations.append({
                    "pod": pod.metadata.name,
                    "container": container.name,
                    "issue": "privileged=true",
                })
            if sc.run_as_non_root is not True:
                violations.append({
                    "pod": pod.metadata.name,
                    "container": container.name,
                    "issue": "runAsNonRoot not set",
                })
            caps = sc.capabilities
            if level == "restricted" and (not caps or not caps.drop or "ALL" not in caps.drop):
                violations.append({
                    "pod": pod.metadata.name,
                    "container": container.name,
                    "issue": "capabilities.drop does not include ALL",
                })
    return violations

kubectl Equivalents

# Label a namespace with restricted enforcement
kubectl label namespace production \
  pod-security.kubernetes.io/enforce=restricted \
  pod-security.kubernetes.io/warn=restricted \
  --overwrite

# Dry-run to test impact before enforcing
kubectl label --dry-run=server --overwrite namespace production \
  pod-security.kubernetes.io/enforce=restricted

# Check which namespaces have PSA labels
kubectl get namespaces -L pod-security.kubernetes.io/enforce

Output Format

{
  "namespace": "production",
  "enforce_level": "restricted",
  "audit_level": "restricted",
  "warn_level": "restricted",
  "pod_violations": [
    {
      "pod": "legacy-app-7f8b9c",
      "container": "app",
      "issue": "privileged=true"
    }
  ],
  "compliant": false
}

references/standards.md (verbatim)

Standards - Pod Security Admission Controller

Kubernetes Pod Security Standards

Profile Controls Enforced
Baseline No privileged, no hostPID/IPC/Network, no hostPorts, restricted volumes, no procMount, restricted seccomp, restricted capabilities
Restricted All Baseline + non-root, drop ALL caps, seccomp required, restricted volume types, no privilege escalation

CIS Kubernetes Benchmark v1.8

  • 5.2.1: Ensure privileged containers are not used
  • 5.2.2-5.2.4: Ensure host namespace sharing is disabled
  • 5.2.5: Ensure privilege escalation is not allowed
  • 5.2.6: Ensure root containers are not admitted
  • 5.2.7: Ensure seccomp profile is set
  • 5.7.3: Apply security context to pods

NIST SP 800-190

  • Section 4.3: Container runtime security
  • Section 5.4: Admission control enforcement

NSA/CISA Kubernetes Hardening Guide v1.2

  • Section 1: Pod Security - Use Pod Security Standards

Compliance Mappings

  • PCI DSS v4.0 Req 2.2: Configuration standards
  • SOC 2 CC6.1: Logical access controls
  • HIPAA 164.312(a)(1): Access controls

references/workflows.md (verbatim)

Workflow - Implementing Pod Security Admission

Phase 1: Assessment

  1. List all namespaces and their current security posture
  2. Run dry-run against restricted profile for each namespace
  3. Document violations and required exemptions

Phase 2: Apply Audit Mode

for ns in production staging; do
  kubectl label namespace $ns \
    pod-security.kubernetes.io/audit=restricted \
    pod-security.kubernetes.io/warn=restricted
done

Phase 3: Fix Violations

  1. Update Deployments/StatefulSets with compliant security contexts
  2. Add seccomp profiles
  3. Switch containers to non-root
  4. Drop ALL capabilities

Phase 4: Enable Enforcement

kubectl label namespace production \
  pod-security.kubernetes.io/enforce=restricted \
  pod-security.kubernetes.io/enforce-version=v1.28

Phase 5: Set Cluster Defaults

  1. Create AdmissionConfiguration with baseline defaults
  2. Apply to kube-apiserver
  3. Exempt system namespaces

Phase 6: Monitor

  1. Watch for FailedCreate events
  2. Review audit logs weekly
  3. Update exemptions as needed

Back to mukul975/Anthropic-Cybersecurity-Skills (817 security skills) or Agent skills.