How does the location path in a Gatekeeper Assign select a field inside a Pod?
answer
- a path, not a patch document
- lists keyed by name, never by index
- a glob matches, it does not create
- MustExist or MustNotExist gates the write
basics
~20 sThe location is a dotted path from the object's root, with list entries picked by a key filter such as spec.containers[name:*]. Missing intermediate fields are created on the way; a glob only matches list entries that already exist.
solid answer
~40 s`location` walks the object like a path: `spec.automountServiceAccountToken` for a scalar near the root, `spec.containers[name:*].imagePullPolicy` to reach into a list. Lists are addressed by their key field, not by index — `[name:*]` means every entry, `[name:app]` one specific entry — and a key containing dots is quoted. Two things trip people up. First, a glob matches what is there; Gatekeeper will not invent a container for you, and `containers` and `initContainers` are separate lists needing separate mutators. Second, `parameters.pathTests` gates the write: each test names a `subPath` and a `condition` of `MustExist` or `MustNotExist`, and if a test fails the mutation is simply skipped for that object — no patch, no error. `MustNotExist` on the target path is the idiom for "set this only when the author left it out".
code
yaml · 19 linesapiVersion: mutations.gatekeeper.sh/v1
kind: Assign
metadata:
name: no-automount-sa-token
spec:
applyTo:
- groups: [""]
versions: ["v1"]
kinds: ["Pod"]
match:
scope: Namespaced
excludedNamespaces: ["kube-system"]
location: "spec.automountServiceAccountToken"
parameters:
pathTests:
- subPath: "spec.automountServiceAccountToken"
condition: MustNotExist
assign:
value: falsego deeper
Know that the location is a dotted path into the object and that list entries are picked by a key filter like [name:*] rather than by position. Being able to read one aloud is enough.
Be ready to write a path for a nested field and to say precisely what happens when it matches nothing: a silent no-op, not an error. Know that pathTests are the only conditional the mutation CRDs offer.
Demonstrate the habit of writing paths against a real admitted object and verifying the result, and be able to separate an applyTo/match miss from a location miss when both present as an unchanged object.
Think about maintainability across an estate: paths are coupled to object shape, so decide who reviews mutators when workload shapes change and how a broken path gets noticed before an auditor notices it.
## The grammar A mutator's `location` is a path expression evaluated against the object being admitted. It has three constructs and no more: 1. **Dotted field access** — `spec.automountServiceAccountToken`, `spec.template.spec.hostNetwork`. 2. **A list key filter** — `spec.containers[name:*]`. Lists in Kubernetes objects are addressed by their identifying key (usually `name`), never by index, because index positions are not stable across edits. `[name:*]` selects every entry, `[name:sidecar]` selects one. 3. **Quoting** — a segment containing dots or slashes is wrapped in quotes, which matters for annotation keys such as `"example.com/owner"`. So `spec.containers[name:*].imagePullPolicy` reads as: from the root, into `spec`, into the `containers` list, every entry, the `imagePullPolicy` field of each. ## What the path will and will not create Gatekeeper fills in missing intermediate **map** fields along the path so you can write a nested field on an object that never declared its parent. What it will not do is invent list members: a glob describes entries that exist. If a Pod declares no containers matching the filter, nothing is written and nothing is reported. This is the single most common cause of a mutator that appears dead. The related trap is list identity. `containers`, `initContainers` and (where used) `ephemeralContainers` are three separate lists. A path that names `containers` says nothing about the others, and a rule intended to cover every container in the Pod needs a mutator per list. ## pathTests: conditional mutation without a policy language `parameters.pathTests` is a list of `{subPath, condition}` entries where the condition is `MustExist` or `MustNotExist`. All tests must pass or the mutator does nothing to that object. This is the only conditional logic the mutation CRDs have, and it covers the two cases that matter: - **`MustNotExist` on the target path** — write the value only if the author did not set one. This is how a platform team supplies a safe default without overriding a team that deliberately chose otherwise. - **`MustExist` on a parent path** — only touch objects that already declare the structure you are editing, so you do not conjure a half-populated block onto objects that have no business carrying one. Because a failed test is a silent skip, pathTests are also a debugging suspect: a rule that was working and stopped working often has a pathTest whose subpath no longer matches the shape of the incoming manifests. ## Matching versus locating Keep three selectors separate in your head, because they fail in different ways: - `applyTo` decides **which kinds** the mutator may edit (group, version, kind). - `match` decides **which instances** of those kinds — namespaces, label selectors, name, scope. - `location` decides **which field inside** the instance. A typo in the first two means the mutator never runs. A typo in the third means it runs and writes nowhere. Both look identical from outside: an object that came out exactly as it went in. ## Practical habit Write the path against a real object, not against the manifest you wish people submitted. Dump an actual admitted Pod, follow the path down it by eye, and only then encode it. Paths written from memory against a Deployment's pod template and then applied to Pods are a recurring source of rules that quietly do nothing.
- What happens when a pathTest fails?The mutation is skipped for that object. The request continues and is stored unchanged, with no error, no annotation and no denial. That is what makes pathTests useful for conditional defaults and also what makes them a prime suspect when a mutator seems to have stopped working.
- Why does spec.containers[name:*].image miss an initContainer?Because the path names the `containers` list, and `initContainers` is a different list on the same Pod. The key filter only iterates the list you named. Covering both means a second mutator, or a second location path, targeting `spec.initContainers[name:*]`.
- Can location target a field the submitted object never declared?For map fields, yes — Gatekeeper creates the missing intermediate structure so you can set a nested field on an object that omitted its parent. For list entries it will not: a glob selects existing members, so a Pod with no matching container simply receives nothing.
saying these in an interview costs you the question
- Thinks a glob creates missing list entries
- Expects an error when the path matches nothing
- Addresses list entries by index instead of key
- Assumes one path covers containers and initContainers