skip to content

What does a Gatekeeper Assign resource do, and how does it differ from a Constraint?

level: juniorimportance: must knowfreq 64%

answer

  1. repairs the object, never refuses
  2. no ConstraintTemplate, no Rego
  3. applyTo, match, location, parameters
  4. four CRDs, one of them metadata-only

basics

~10 s

A Gatekeeper Assign is a mutator: at admission it writes a value into a field of the incoming object, so the object is stored changed instead of rejected. A Constraint only inspects and denies.

solid answer

~40 s

`Assign` is one of Gatekeeper's mutation CRDs, alongside `AssignMetadata` (adds a label or annotation), `ModifySet` (adds or removes members of a list treated as a set) and `AssignImage` (rewrites the domain, path or tag of an image reference). An Assign has three moving parts: `applyTo`, naming the group/version/kind it can edit; `match`, narrowing by namespace, label selector, name and scope; and `location`, the path to the field, with the new value under `parameters.assign.value`. Unlike a Constraint it carries no Rego and needs no ConstraintTemplate — the whole rule is declarative YAML. And unlike a Constraint it has no `enforcementAction` and cannot deny anything: the outcome is a silently repaired object, or nothing at all. Mutation runs in Gatekeeper's mutating webhook, so validation sees the object after the repair.

go deeper

for a junior

Be ready to say in one line what a mutator does: it edits the incoming object at admission instead of refusing it. Naming the four mutation resources and what each one touches is enough here.

for a middle

Expect to walk the Assign spec field by field — applyTo, match, location, parameters.assign.value — and to explain why no Rego and no ConstraintTemplate are involved.

for a senior

Show that you plan for the silence. A mutator gives no denial and no status message, so describe how you confirm it actually fired on the objects you care about before you call the rollout done.

for a principal

Own the boundary: which fields the platform sets on everyone's behalf versus which stay the application team's to declare, and who approves each time that list grows.

## Two different jobs Gatekeeper ships two families of cluster objects. Constraints **validate**: they run a Rego `violation` rule supplied by a ConstraintTemplate and their answer is allow or deny. Mutators **repair**: they patch the object on its way through admission and have no way to say no. Both are ordinary Kubernetes resources you apply with `kubectl` and ship through the same GitOps flow, which is the whole point of Gatekeeper's design — the rule is a cluster object, not a binary you deploy. ## The mutation CRDs | Resource | What it writes | |---|---| | `Assign` | any non-metadata field, set to a literal value | | `AssignMetadata` | a label or annotation — and only one that is not already present | | `ModifySet` | members of a list treated as a set, `merge` to add or `prune` to remove | | `AssignImage` | the domain, path and tag components of an image reference | The restriction on `Assign` is worth memorising: it is not allowed to write into `metadata`. That is exactly why `AssignMetadata` exists, and `AssignMetadata` is deliberately weak — it may **add** a label or annotation, never overwrite an existing value. A rule that stamps `owner: platform` on every namespaced object will leave a team's own `owner` value alone. ## Anatomy of an Assign - **`applyTo`** — a list of `{groups, versions, kinds}`. Core objects such as Pod use `groups: [""]`, the empty string, not `"core"` and not `"v1"`. - **`match`** — which of those objects, by `namespaces`, `excludedNamespaces`, `labelSelector`, `namespaceSelector`, `name` and `scope`. Both `applyTo` and `match` must be satisfied. - **`location`** — a dotted path from the object root to the field, with list entries selected by a key filter such as `spec.containers[name:*]`. - **`parameters.assign.value`** — the value to write. `parameters.pathTests` can require a subpath to exist or not exist before the write lands. A typical first rule sets `spec.automountServiceAccountToken` to `false` on Pods outside a few system namespaces: the workload never asked for a service-account token, and now it does not get one mounted, with no ticket filed against the owning team. ## What that buys, and what it costs The benefit is that nobody is blocked. A validating rule for the same field turns into a queue of pull requests across every team; the mutator just fixes it. The cost is that **there is no feedback channel at all**. A Constraint that denies produces an error message on the developer's terminal and, in `dryrun` mode, a violation recorded in the Constraint's own status. A mutator that fires produces nothing, and — more importantly — a mutator that matches nothing also produces nothing. Silence is both the success signal and the failure signal, so you have to verify separately that the field really is set on the objects you care about. Mutation also applies only to requests going through admission — creates and updates. Objects already sitting in etcd when you install the mutator were admitted before it existed and are untouched by it. ## The common wrong answers Candidates often say a mutator can "deny if it can't fix". It cannot; the two behaviours live in different resources, and if you want a hard stop you write a Constraint as well. Others reach for Rego, assuming every Gatekeeper rule is Rego — the mutation CRDs are pure structured YAML with no policy language in them, which is a large part of why teams adopt them first. And several will try to set a label with `Assign`, which is rejected: metadata belongs to `AssignMetadata`.

  • Can an Assign set a label on the incoming object?
    No. `Assign` is not permitted to write into `metadata`; that is what `AssignMetadata` is for. And `AssignMetadata` is add-only — it can set a label or annotation the object does not have, but it will not overwrite a value the author already supplied.
  • Does a mutator have an enforcementAction like a Constraint does?
    No. `enforcementAction` is a Constraint field. A mutator either matched and wrote, or it did not — there is no deny tier, no warn tier and no message anywhere. If you need to know whether it is landing, verify out of band: inspect a server-side dry-run of a real object, or run a Constraint over the same field.
  • What does AssignImage let you change about an image reference?
    It splits the reference into components and sets them independently: `assignDomain` for the registry host, `assignPath` for the repository path, `assignTag` for the tag. The common use is rewriting the domain to an internal pull-through mirror so workloads stop pulling straight from a public registry.

saying these in an interview costs you the question

  • Says a mutator can reject an object it cannot fix
  • Thinks Assign needs a ConstraintTemplate and Rego
  • Uses Assign to write metadata.labels
  • Expects a mutator to fix already-running Pods

context