Feature State: Gatekeeper version v3.11+ (beta)
gator CLI is a tool for evaluating Gatekeeper ConstraintTemplates and
Constraints in a local environment.
To build from source:
go get github.com/open-policy-agent/gatekeeper/cmd/gator
Install with Homebrew:
brew install gator
gator test subcommand
gator test allows users to test a set of Kubernetes objects against a set of
Templates and Constraints. The command returns violations when found and
communicates success or failure via its exit status. This command will also
attempt to expand any resources passed in if a supplied
matches these resources.
gator verify command was first called
gator test. These names were
changed to better align
gator with other projects in the open-policy-agent
gator test supports inputs through the
--image flags, and
via stdin. The three methods of input can be used in combination or individually. The
--image flags are repeatable.
--filename flag can specify a single file or a directory. If a file is
specified, that file must end in one of the following extensions:
.yml. Directories will be walked, and any files of extensions other
than the aforementioned three will be skipped.
For example, to test a manifest (piped via stdin) against a folder of policies:
cat my-manifest.yaml | gator test --filename=template-and-constraints/
Or you can specify both as flags:
gator test -f=my-manifest.yaml -f=templates-and-constraints/
--imageflag is in alpha stage.
--image flag specifies a content addressable OCI artifact containing
policy files. The image(s) will be copied into the local filesystem in a
temporary directory, the location of which can be overridden with
flag. Only files with the aforementioned extensions will be processed. For
information on how to create OCI policy bundles, see
the Bundling Policy into OCI Artifacts
For example, to test a manifest (piped via stdin) against an OCI Artifact containing policies:
cat my-manifest.yaml | gator test --image=localhost:5000/gator/template-library:v1 \
gator test will return a
0 exit status when the objects, Templates, and
Constraints are successfully ingested, no errors occur during evaluation, and no
violations are found.
An error during evaluation, for example a failure to read a file, will result in
1 exit status with an error message printed to stderr.
Policy violations will generate a
1 exit status as well, but violation
information will be printed to stdout.
While violation data will always be returned when an object is found to be
violating a Constraint, the exit status can vary. A constraint with
spec.enforcementAction: "" or
spec.enforcementAction: deny will produce a
1 exit code, but other enforcement actions like
dryrun will not. This is
meant to make the exit code of
1 consistent with rejection of the object by
Gatekeeper's webhook. A Constraint set to
warn would not trigger a rejection
in the webhook, but would produce a violation message. The same is true for
that constraint when used in
gator test supports a
--output flag that allows the user to specify a
structured data format for the violation data. This information is printed to
The allowed values are
json, specified like:
gator test --filename=manifests-and-policies/ --output=json
gator verify subcommand
Writing Test Suites
gator verify organizes tests into three levels: Suites, Tests, and Cases:
- A Suite is a file which defines Tests.
- A Test declares a ConstraintTemplate, a Constraint, and Cases to test the Constraint.
- A Case defines an object to validate and whether the object is expected to pass validation.
Any file paths declared in a Suite are assumed to be relative to the Suite itself. Absolute paths are not allowed. Thus, it is possible to move around a directory containing a Suite, and the files it uses for tests.
To be valid, a Suite file must declare:
gator verify silently ignores files which do not declare these. A Suite may
declare multiple Tests, each containing different Templates and Constraints.
Each Test in a Suite is independent.
Each Suite contains a list of Tests under the
A Test compiles a ConstraintTemplate, and instantiates a Constraint for the ConstraintTemplate. It is an error for the Constraint to have a different type than that defined in the ConstraintTemplate spec.crd.spec.names.kind, or for the ConstraintTemplate to not compile.
Each Test contains a list of Cases under the
A Case validates an object against a Constraint. The case may specify that the object is expected to pass or fail validation, and may make assertions about the returned violations (if any).
A Case must specify
assertions and whether it expects violations. The simplest
way to declare this is:
The Case expects at least one violation:
- violations: yes
The Case expects no violations:
- violations: no
Assertions contain the following fields, acting as conditions for each assertion to check.
violationsis either "yes", "no", or a non-negative integer.
- If "yes", at least one violation must otherwise match the assertion.
- If "no", then no violation messages must otherwise match the assertion.
- If a nonnegative integer, then exactly that many violations must match. Defaults to "yes".
messagematches violations containing the exact string specified.
messageis case-sensitive. If not specified or explicitly set to empty string, all messages returned by the Constraint are considered matching.
A Case may specify multiple assertions. For example:
- name: both-disallowed
- violations: 2
- message: initContainer
- message: container
This Case specifies:
- There are exactly two violations.
- There is exactly one violation containing "initContainer".
- There is exactly one violation containing "container".
It is valid to assert that no violations match a specified message. For example, the below is valid:
- violations: yes
- violations: no
This Case specifies that there is at least one violation, and no violations contain the string "foobar".
A Case may specify
inventory, which is a list of paths to files containing
Kubernetes objects to put in
data.inventory for testing referential
More examples of working
gator verify suites are available in the
To run a specific suite:
gator verify suite.yaml
To run all suites in the current directory and all child directories recursively
gator verify ./...
To only run tests whose full names contain a match for a regular expression, use
gator verify path/to/suites/... --run "disallowed"
Validating Metadata-Based Constraint Templates
gator verify may be used with an
object to test your constraints. This can be helpful to simulate a certain operation (
Recall that the
input.review.user can be accessed in the Rego code (see Input Review for more guidance).
A few examples for how to structure your yaml can be found here.
AdmissionReview object can be specified where you would specify the object under test above:
- name: both-disallowed
- violations: 1
gator test are different enforcement points and they don't have the
AdmissionReview request metadata.
gator verify --help for more information.
gator expand subcommand
gator expand allows users to test the behavior of their Expansion configs. The
command accepts a file or directory containing the expansion configs, which
should include the resource(s) under test, the
optionally any Mutation CRs. The command will output a manifest containing the
If the mutators use spec.match.namespaceSelector, the namespace the resource belongs to must be supplied in order to correctly evaluate the match criteria. If a resource is specified for expansion but its non-default namespace is not supplied, the command will exit 1.
gator expand expects a
flag. The flags can be used individually, in combination, and/or repeated.
gator expand --filename="manifest.yaml" –filename="expansion-policy/"
Or, using an OCI Artifact for the expansion configuration:
gator expand --filename="my-deployment.yaml" --image=localhost:5000/gator/expansion-policy:v1
gator expand will output to stdout, but a
–outputfile flag can be
specified to write the results to a file.
gator expand --filename="manifest.yaml" –outputfile="results.yaml"
gator expand can output in
json (default is
gator expand --filename="manifest.yaml" –format="json"
gator expand –help for more details.
gator expand will exit 1 if there
is a problem parsing the configs or expanding the resources.
Bundling Policy into OCI Artifacts
It may be useful to bundle policy files into OCI Artifacts for ingestion during
CI/CD workflows. The workflow could perform validation on inbound objects using
A policy bundle can be composed of any arbitrary file structure, which
will walk recursively. Any files that do not end in
json|yaml|yml will be
gator does not enforce any file schema in the artifacts; it only
requires that all files of the support extensions describe valid Kubernetes
We recommend using the Oras CLI to create OCI
artifacts. For example, to push a bundle containing the 2 local directories
oras push localhost:5000/gator/policy-bundle:v1 ./constraints/:application/vnd.oci.image.layer.v1.tar+gzip \
This expects that the
template_library directories are at
the path that this command is being run from.
Duplicate violation messages
Rego de-duplicates identical violation messages. If you want to be sure that a test returns multiple violations, use a unique message for each violation. Otherwise, if you specify an exact number of violations, the test may fail.
Matching is case-sensitive
Message declarations are case-sensitive. If a test fails, check that the expected message's capitalization exactly matches the one in the template.
Referential constraints and Namespace-scoped resources
Gator cannot determine if a type is Namespace-scoped or not, so it does not
assign objects to the default Namespace automatically. Always specify
metadata.namespace for Namespace-scoped objects to prevent test failures, or
to keep from specifying templates which will fail in a real cluster.
gator is only automatically tested on Linux for each commit. If you want to
gator on other systems, let us know by replying to
gator verify has been manually tested on Windows and works as of
. Continued functionality is not guaranteed.
File paths which include backslashes are not portable, so suites using such paths will not work as intended on Windows.