DEV Community

StarkMan
StarkMan

Posted on

Admission Control in Kubernetes: Where Policy Actually Gets Enforced

Admission Control in Kubernetes: Where Policy Actually Gets Enforced

A cluster hardens over time through decisions recorded in YAML. Somewhere in that history is a privileged: true that was added for a debugging session, a hostPath mount for a monitoring agent, and a service account with cluster-wide list permissions that nobody remembers creating. Admission control is the mechanism that stops those decisions from being made again, and understanding where it runs explains why some policies work in one cluster and not in another.

The order of evaluation

A request to the API server passes through authentication, authorization, then admission. Admission has two phases. Mutating admission may change the object, and validating admission may only accept or reject it. Built-in controllers such as ServiceAccount and ResourceQuota run alongside webhooks in this chain.

The order matters in practice. A mutating webhook that injects a sidecar changes the pod that validating webhooks then see, so a validating rule written against the original manifest can reject an object that was already modified. Policies that need to reason about the final state must therefore run after the webhook that mutates it, which is controlled by reinvocationPolicy and by webhook ordering.

Built-in controls that cover more than they appear to

Pod Security Admission applies a labelled level to a namespace: privileged, baseline or restricted. The restricted level sets a demanding baseline that includes non-root execution, a read-only root filesystem option, dropped capabilities and a seccomp profile.

Its strength is that it is built in and needs no webhook infrastructure. Its limitation is granularity. The level applies to a namespace, so a cluster with mixed workloads either splits into more namespaces or accepts the stricter level everywhere. Applying it in warn mode first gives a view of what would be rejected before anything breaks.

apiVersion: v1
kind: Namespace
metadata:
  name: payments
  labels:
    pod-security.kubernetes.io/enforce: restricted
    pod-security.kubernetes.io/warn: restricted
Enter fullscreen mode Exit fullscreen mode

Policy engines and what they add

A policy engine such as Gatekeeper or Kyverno adds policy expressed as code with parameters, so a rule can be reused across clusters with different thresholds. A constraint that forbids host path volumes takes a parameter listing allowed paths, and the same constraint definition then serves a cluster where nothing is allowed and a cluster where one monitoring path is permitted.

This matters for the audit trail as much as for enforcement. A constraint with parameters produces an artefact that explains what was permitted and under which condition, which is more useful during a review than a webhook whose behaviour exists only in a container image.

Two operational details decide whether a policy engine helps or hurts. Webhooks should fail closed for controls that are security-relevant, so an unavailable policy engine blocks the request rather than allowing it. And the policy engine itself runs in the cluster it governs, so its own namespace needs to be excluded from the policies it enforces, with that exclusion documented rather than discovered.

Making policy stick

The failure mode for admission policy is not a missing webhook. It is a legitimate exception granted during an incident and never removed. A time-bounded exception, recorded in the policy repository with an owner and an expiry, keeps the audit trail intact, and a scheduled report of active exceptions turns the inevitable accumulation into a visible list.

References

Top comments (0)