Skip to content
Back to skills

Webapp Implementing Pod Security Admission Controller

ASecurity

Implement Kubernetes Pod Security Admission to enforce baseline and restricted security profiles at namespace level using built-in admission controller.

  • 2 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added November 7, 2026
securitygobashnodekubernetestestingapisecurity

Works with

  • api

Security analysis

A100/100

Scanned November 7, 2026

npx -y skills add bitbytelabio/arsenal --skill webapp-implementing-pod-security-admission-controller --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Webapp Implementing Pod Security Admission Controller?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Webapp Implementing Pod Security Admission Controller
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/bitbytelabio-webapp-implementing-pod-security-admission-control/badge)](https://www.skillsdirectory.com/skills/bitbytelabio-webapp-implementing-pod-security-admission-control)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: webapp-implementing-pod-security-admission-controller
description: Implement Kubernetes Pod Security Admission to enforce baseline and restricted security profiles at namespace level using built-in admission controller.
domain: webapp
category: container-security
hide: true
license: Apache-2.0
metadata:
  manifest_entry: src/corpus/webapp-implementing-pod-security-admission-controller/SKILL.md
---
# 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

- When deploying or configuring implementing pod security admission controller 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

## Common Misconfigurations & Verification

- **`enforce` mode never set:** a namespace (or the cluster `AdmissionConfiguration` default) configured with only `audit`/`warn` logs violations but admits everything. Only `enforce` blocks. Verify: `kubectl get ns -L pod-security.kubernetes.io/enforce`.
- **Cluster-default exemptions too broad:** the `PodSecurityConfiguration` `exemptions.namespaces` list (kube-system, monitoring, falco...) is a hard bypass - anything scheduled there skips PSA entirely. Keep it minimal and review it.
- **AdmissionConfiguration not wired in:** the `--admission-control-config-file` flag and hostPath mount must be present in `kube-apiserver.yaml`, or the cluster default silently doesn't apply. Confirm the apiserver came up with the flag.
- **Label typos / unpinned version:** `pod-security.kubernetes.io/enforce` with a misspelled key is ignored, and `enforce-version: latest` can shift checks on upgrade - pin a version (e.g. `v1.28`).
- **PSA evaluates spec only:** it can't see a root `USER` baked into the image or verify image provenance; combine with Gatekeeper/Kyverno for those.
- **Verify before and after:** `kubectl label --dry-run=server --overwrite ns <ns> pod-security.kubernetes.io/enforce=restricted` lists violators; after enabling enforce, `kubectl run test --image=nginx -n <ns>` should be **rejected** (nginx runs as root under restricted).

## 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

```yaml
# 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
```

```yaml
# 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
```

```yaml
# Privileged for system namespaces
apiVersion: v1
kind: Namespace
metadata:
  name: kube-system
  labels:
    pod-security.kubernetes.io/enforce: privileged
```

### Apply Labels with kubectl

```bash
# 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

```bash
# 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)

```yaml
# /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

```bash
# 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

```yaml
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

```yaml
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
```bash
# 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
```bash
# 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)
```bash
# 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
```bash
# Check audit logs for violations
kubectl get events --field-selector reason=FailedCreate -A
```

### Step 5: Enable Enforcement
```bash
kubectl label namespace production \
  pod-security.kubernetes.io/enforce=restricted
```

## Monitoring

```bash
# 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

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.