Kubernetes v1.36 Introduces Manifest-Based Admission Control for Irremovable Policies

By

The Problem: Why Admission Policies Are Vulnerable

Enforcing security policies across a fleet of Kubernetes clusters often feels like a never‑ending game of cat and mouse. Admission policies are themselves API objects, meaning they don’t exist until someone creates them—and anyone with sufficient privileges can delete them at any time. This creates a frustrating chicken‑and‑egg scenario: you can’t protect your cluster with policies until the policies are created, but during that creation window, the cluster is essentially unprotected.

Kubernetes v1.36 Introduces Manifest-Based Admission Control for Irremovable Policies

Even worse, there’s a significant gap during cluster bootstrap. The API server starts serving requests before your admission configurations are created and active. The same gap appears when restoring from a backup or recovering from an etcd failure, leaving a window where no policy enforcement exists.

Kubernetes also has a self‑protection blind spot: admission webhooks and policies cannot intercept operations on their own configuration resources. For example, Kubernetes deliberately skips invoking webhooks on ValidatingWebhookConfiguration objects to avoid circular dependencies. This means a sufficiently privileged user can delete critical admission policies without any intervention from the admission chain itself.

As a result, the Kubernetes SIG API Machinery recognized the need for a mechanism that says, “these policies are always on, full stop.”

Introducing Manifest-Based Admission Control (Alpha)

Kubernetes v1.36 ships an alpha feature that directly addresses this gap: manifest‑based admission control. The idea is simple: instead of relying solely on API objects, you define admission webhooks and CEL‑based policies as YAML files stored on disk. The API server loads these files at startup—before it begins serving any requests—ensuring that critical policies are always active from the moment the cluster is available.

How to Configure It

You enable the feature by adding a staticManifestsDir field to your existing AdmissionConfiguration file (the one you pass to the API server via the --admission-control-config-file flag). Point that field to a directory containing your policy YAML files, and the API server will load them during its initialization sequence.

apiVersion: apiserver.config.k8s.io/v1
kind: AdmissionConfiguration
plugins:
- name: ValidatingAdmissionPolicy
  configuration:
    apiVersion: apiserver.config.k8s.io/v1
    kind: ValidatingAdmissionPolicyConfiguration
    staticManifestsDir: "/etc/kubernetes/admission/validating-policies/"

The manifest files themselves are standard Kubernetes resource definitions. The only extra requirement is that every object defined in these manifests must have a name ending with .static.k8s.io.

The .static.k8s.io Suffix Requirement

This reserved suffix serves two purposes. First, it prevents naming collisions between manifest‑based policies and API‑created ones. Second, it makes it easy to identify the source of an admission decision when examining metrics or audit logs—if you see a policy name ending in .static.k8s.io, you know it came from a disk‑based manifest and cannot be removed through the API.

A Concrete Example: Denying Privileged Pods

Here’s a complete example that denies privileged containers outside the kube-system namespace, using a CEL‑based ValidatingAdmissionPolicy:

apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
  name: "deny-privileged.static.k8s.io"
  annotations:
    kubernetes.io/description: "Deny launching privileged pods, anywhere this policy is applied"
spec:
  matchConstraints:
    resourceRules:
    - apiGroups: [""]
      apiVersions: ["v1"]
      operations: ["CREATE", "UPDATE"]
      resources: ["pods"]
  validations:
  - expression: "!has(object.spec.containers) || object.spec.containers.all(c, !has(c.securityContext) || !has(c.securityContext.privileged) || c.securityContext.privileged != true) && (!has(object.spec.initContainers) || object.spec.initContainers.all(c, !has(c.securityContext) || !has(c.securityContext.privileged) || c.securityContext.privileged != true))"
    message: "Privileged containers are not allowed outside kube-system."
   - namespaceSelector:
      matchExpressions:
      - key: kubernetes.io/metadata.name
        operator: NotIn
        values: ["kube-system"]

When placed in the staticManifestsDir directory, this policy is loaded before the API server starts serving requests, ensuring that privileged pods cannot be created even during the initial bootstrap phase.

Benefits and Use Cases

Manifest‑based admission control closes the critical bootstrap gap. Whether you’re starting a brand‑new cluster, recovering from a disaster, or simply want to ensure that certain policies cannot be deleted accidentally or maliciously, this feature provides a reliable, always‑active layer of enforcement.

Key benefits include:

  • Always‑on enforcement – Policies are loaded before any user request reaches the API server.
  • Self‑protection – Policies loaded from disk cannot be altered or deleted through the Kubernetes API, eliminating the privileged‑user loophole.
  • Clear auditability – The .static.k8s.io suffix makes it trivial to identify which policies are manifest‑based.
  • No circular dependency – Because these policies are loaded at startup, they avoid the chicken‑and‑egg problem that plagues API‑based admission configurations.

This feature is currently in alpha. The Kubernetes SIG API Machinery encourages you to test it in your own clusters and provide feedback through the usual Kubernetes channels.

Tags:

Related Articles

Recommended

Discover More

AD CS Escalation and Misuse: Key Questions on Techniques, Tools, and DetectionHow to Evaluate Weather Forecasting Models for Extreme Events: A Step-by-Step GuideMachine-Speed Attacks Force Cybersecurity Rethink: Automation and AI Now Critical for DefenseAI Efficiency Gains Come at a Hidden Cost: The Slow Erosion of Team TrustTransform Your PS5 into a Steam Gaming Machine: A Guide to Installing Linux