Enforce your rules automatically at the gate and watch for what gets past it. Block non-conforming or unsigned pods with Kyverno/OPA admission policies, and detect malicious behavior in running containers with Falco.
An admission controller intercepts every create/update request to the Kubernetes API and can reject or mutate it before it takes effect. This is where you enforce organization-wide rules — no privileged pods, images only from your registry, required labels — as code, so a bad manifest never reaches the cluster regardless of who applied it. Kyverno and OPA Gatekeeper are the two common engines.
kubectl apply -> API server -> [ADMISSION WEBHOOK] -> etcd (stored) -> scheduled
|
your policy runs HERE and can:
VALIDATE reject if it violates policy
MUTATE inject defaults (e.g. securityContext)
Pod Security Standards (lesson 5) is built-in admission for the common
cases; Kyverno/OPA handle everything else: registries, signatures,
labels, resource limits, custom org rules.Kyverno expresses policies as Kubernetes resources — no new language to learn. A validating policy rejects any pod that breaks a rule; here, blocking images from untrusted registries. Combined with the securityContext and signature rules, admission control becomes the automated enforcement of everything the earlier lessons taught.
# Kyverno: only allow images from our registry (no docker.io randomness)
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata: { name: restrict-registries }
spec:
validationFailureAction: Enforce # reject, don't just warn
rules:
- name: only-approved-registry
match:
any: [{ resources: { kinds: ["Pod"] } }]
validate:
message: "Images must come from registry.example.com"
pattern:
spec:
containers:
- image: "registry.example.com/*"
# also common: require runAsNonRoot, drop-ALL caps, deny :latest tags,
# require resource limits — all as short Kyverno rules.This is where the Supply Chain course pays off: an admission policy can require that every image is signed by your pipeline and carries valid provenance, rejecting anything unverified at schedule time. A compromised registry entry or an unsigned image simply cannot run — closing the loop between "we signed it" and "only signed things execute."
# Kyverno verifyImages: only run images signed by OUR CI identity
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata: { name: require-signed-images }
spec:
validationFailureAction: Enforce
rules:
- name: verify-signature
match: { any: [{ resources: { kinds: ["Pod"] } }] }
verifyImages:
- imageReferences: ["registry.example.com/*"]
attestors:
- entries:
- keyless:
issuer: https://token.actions.githubusercontent.com
subject: "https://github.com/my-org/*"
# unsigned or wrong-identity image -> pod creation DENIED.Prevention is never perfect, so watch running containers for behavior that should never happen. Falco taps kernel syscalls and alerts on suspicious activity — a shell spawned in a container, an unexpected outbound connection, a write to a sensitive path. It is the container-world equivalent of the detection you build in the Threat Detection course, and it catches the attacker who got past every gate.
# a Falco rule: alert when a shell is spawned inside a container
- rule: Terminal shell in container
desc: A shell was run inside a container (often post-exploitation)
condition: >
spawned_process and container
and shell_procs and proc.tty != 0
output: >
Shell spawned in container (user=%user.name container=%container.name
proc=%proc.cmdline image=%container.image.repository)
priority: WARNING
# Falco ships curated rules for: crypto-miners, package installs at runtime,
# writes to /etc, contact with cloud metadata (SSRF), privilege escalation.
# Route alerts to your SIEM -> this is detection engineering for containers.