Skip to content

Add gator support for evaluating resources against in-cluster policies #4714

Description

@JaydipGabani

Summary

Add a gator mode that evaluates arbitrary resources — local manifests, stdin, or rendered output — against the ConstraintTemplates and Constraints currently deployed in a cluster, and reports whether they would be admitted.

gator test already accepts policies from local files (-f) and from OCI images (-i). This asks for a third policy source: the live cluster.

Motivation

Today the only reliable way to find out whether a resource will be rejected by the policies actually enforcing in a cluster is to attempt the apply. gator test -f answers a different question — it tells you what your local copy of the policies says, not what the cluster will do. Those two drift, and the drift is invisible until an apply fails.

Use cases:

  1. Pre-apply check. "Will this manifest be admitted by prod?" from a workstation or pipeline, without applying it and without needing write access.
  2. App teams that do not own the policies. They have no copy of the ConstraintTemplates and no practical way to obtain a current one; the cluster is the source of truth.
  3. Platform / GitOps pre-flight. Config management and delivery tools want to surface policy violations before publishing a release. Integrators do this today by hand-building an AdmissionReview and POSTing it to gatekeeper-webhook-service — see below for why that is a poor interface.
  4. Explaining a rejection after the fact. Re-run the same resource and get the full violation list rather than the truncated denial message.
  5. Multi-cluster. Same manifest, different clusters with different constraint sets. Check each one without applying to any.

Why not POST to the webhook

Integrators fill this gap today by synthesizing an AdmissionReview and sending it directly to Gatekeeper's webhook Service. That path has real problems:

  • Requires network reachability to the webhook Service, so the caller effectively has to run in-cluster.
  • Easy to get namespace, userInfo, and operation wrong, and each of those silently changes which constraints match. A wrong namespace produces a clean result rather than an error.
  • Constraints with enforcementAction: warn or dryrun return allowed: true. Callers that only inspect denials miss them entirely.
  • No stable contract. It is an internal admission endpoint, not a documented compatibility surface, so anything built on it can break without notice.

A supported gator mode gives this use case a real, versioned interface and lets us keep the webhook payload private.

Proposed Behavior

# evaluate a manifest against whatever policies are live in the current context
gator test -f deployment.yaml --from-cluster

# pin the cluster
gator test -f manifests/ --from-cluster --kubeconfig ~/.kube/config --context prod

# from a renderer, over stdin
helm template ./chart | gator test --from-cluster

# supply the namespace used for match evaluation when the manifest omits it
gator test -f deployment.yaml --from-cluster --assume-namespace payments

# CI gating
gator test -f manifests/ --from-cluster --output json

Flag naming is illustrative — see the tracking issue for the shared surface.

Key Design Considerations

  • Policy source. Read ConstraintTemplates and Constraints through the API server. This needs only get/list on constrainttemplates.templates.gatekeeper.sh and the generated constraint CRDs. No webhook access and no cluster-admin. pkg/gator/policy/client already has a dynamic client that lists ConstraintTemplates from kubeconfig and can be extended rather than duplicated — though it currently uses clientcmd.NewDefaultClientConfigLoadingRules() with empty ConfigOverrides, so --kubeconfig / --context plumbing does not exist yet.

  • Match evaluation. spec.match has to be evaluated client-side, including namespaceSelector, which requires the target Namespace object. When the input manifest has no namespace, resolution must be explicit (--assume-namespace) rather than silently matching nothing — a false "no violations" is worse than an error here.

  • Enforcement actions. Report deny, warn, and dryrun distinctly, and honour scopedEnforcementActions for the webhook vs audit scope. A resource that only trips dryrun constraints is not the same as a clean resource, and callers need to be able to tell them apart.

  • Referential constraints. data.inventory has to come from somewhere. Options include reading the cluster's Config/SyncSet to learn which GVKs are synced and pulling those, or requiring the caller to supply them. Whichever we pick, output must state what was and was not populated, so results are never silently under-approximated.

  • External data providers. Cannot generally be reached client-side. Constraints that use external_data should either fail loudly or be reported as unevaluated. They must never silently pass.

  • Engine parity. Rego and CEL / K8sNativeValidation, plus the VAP-generated path where applicable. gator test already defaults --enable-k8s-native-validation to true.

  • Expansion. ExpansionTemplate should apply, so a Deployment is checked as its generated Pod the way admission does.

  • Mutation. Admission mutates before it validates. Decide whether to apply Assign / AssignMetadata / ModifySet pulled from the cluster, or document explicitly that mutation is not simulated. Silently skipping it produces results that disagree with the real apply.

  • Version skew. gator's embedded frameworks/constraint version may differ from the cluster's Gatekeeper version. Results are an approximation. Say so, and consider reporting the cluster's Gatekeeper version alongside the output.

Relationship to #4484

#4484 proposes gator audit for resources already in the cluster. This issue covers resources not yet in the cluster.

They share almost all of the plumbing: kubeconfig handling, loading policies from the API server, client-side spec.match evaluation, data.inventory construction, output formats, and exit codes. They should land on a common implementation and a consistent flag surface rather than two divergent ones. Tracked together in #4715.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions