When using konstraint create
, Konstraint will only generate templates and constraints for policy files with at least one violation[]
rule. The violation
rule is required by Gatekeeper when evaluating policies on a Kubernetes cluster.
When using konstraint doc
, Konstraint will create documentation for each policy file and assign a severity based on the rule names found in the policy.
The following rule names are organized into their own sections as they have special meaning within the context of Gatekeeper and Conftest:
violation
warn
If a policy file does not contain any of the above rules, the policy is added to the Other
section.
The Rego for the libraries will be added to the generated ConstraintTemplate
if and only if the policy imports the library. This helps prevent importing Rego code that will go unused.
The name of the templates and constraints are derived from the name of the folder that the policy was found in.
For example, a policy found in: policies/pod-volume-size-limits/src.rego
generates the following in the policies/pod-volume-size-limits
directory:
-
template.yaml
(defining a ConstraintTemplate)- kind: ConstraintTemplate
- name: podvolumesizelimits
- CRD kind (to add to Kubernetes API): PodVolumeSizeLimits
-
constraint.yaml
(implementing the above ConstraintTemplate)- kind: PodVolumeSizeLimits
- name: podvolumesizelimits
When using the --output
flag, all templates and constraints will be generated in the path specified in the parameter with the format:
- constraint_PodVolumeSizeLimits.yaml
- template_PodVolumeSizeLimits.yaml
NOTE: While not technically required, the tool works best with a folder structure similar to how Gatekeeper itself structures policies and templates.
To further promote that the .rego
file is the source of truth for policy, a block comment can be added to each policy file. Konstraint uses the OPA Metadata Annotations to achieve this. The OPA metadata annotations are a YAML document in the comments above the package declaration preceded by a line containing the METADATA
tag. Standard metadata fields are use where possible, but additional Gatekeeper-specific annotations are used under the custom
metadata key as necessary. The metadata comment block is also what is used when generating documentation via the doc
command.
This comment block should:
- Include a title that succinctly describes the policy.
- Include a human readable description of what the policy does.
- Set the matchers used when generating the Constraints.
It may also specify the enforcement action (deny
, warn
, or dryrun
) that Gatekeeper should take when a resource violates the constraint. If no enforcement action is specified, Konstraint defaults to using deny
to align with Gatekeeper's default action. If the enforcement is set to dryrun
, the policy will be skipped in the documentation generation.
# METADATA
# title: Pods must not run with access to the host IPC
# description: >-
# Pods that are allowed to access the host IPC can read memory of
# the other containers, breaking that security boundary.
# custom:
# enforcement: dryrun
package pod_deny_host_ipc
import data.lib.core
import data.lib.pods
violation[msg] {
pod_has_hostipc
msg := core.format(sprintf("%s/%s: Pod allows for accessing the host IPC", [core.kind, core.name]))
}
pod_has_hostipc {
pods.pod.spec.hostIPC
}
Any matchers that Gatekeeper supports can be added under the custom.matchers
annotation. These matchers are embedded into the ConstraintTemplate
resource as-is. The example below will create a ConstraintTemplate
that only applies to Kubernetes Deployment resources in namespaces named foo
, bar
, or baz
.
# METADATA
# title: Matchers example
# description: Only applies to Deployments in the 'foo', 'bar', and 'baz' namespaces.
# custom:
# matchers:
# kinds:
# - apiGroups:
# - apps
# kinds:
# - Deployment
# namespaces:
# - foo
# - bar
# - baz
package main
import data.lib.core
violation[{"msg": msg}] {
msg := sprintf("%v is a Deployment in the foo, bar, or baz namespace", [core.resource])
}
In some scenarios, you may wish for Konstraint to skip the generation of the Constraint
resource for a policy and manage that externally. To do so, add the skipConstraint: true
annotation in the custom metadata section.
You can also skip the generation of both the Constraint
and ConstraintTemplate
resource with the skipTemplate: true
annotation
in the custom metadata section.
Previously Konstraint had custom annotation format, such as @title
or @kinds
, which is a legacy format and will be removed in future releases.
To aid with transition to OPA Metadata format, a conversion tool is provided as konstraint convert
Gatekeeper has the ability for a single ConstraintTemplate
resource to be used by multiple Constraint
s. One of the reasons for this is that it allows for passing input parameters to the policy so a single policy to avoid duplication. Konstraint supports these input parameters via the parameters
object in the custom metadata section. NOTE: When input parameters are specified, Konstraint skips the generation of the Constraint
resource unless the --partial-constraint
flag is set.
The contents of the parameters
key must be a dictionary (aka map) where the key is the name of the parameter following the OpenAPI V3 schema. This means each dictionary must, at a minimum, also include a type
field that indicates what the type of the input is. The example below demonstrates an input that blocks resources that are missing any of the required labels specified in the parameters.
# METADATA
# title: Required Labels
# description: >-
# This policy allows you to require certain labels are set on a resource.
# custom:
# parameters:
# labels:
# type: array
# description: Array of required label keys.
# items:
# type: string
package required_labels
import data.lib.core
violation[msg] {
missing := missing_labels
count(missing) > 0
msg := sprintf("%s/%s: Missing required labels: %v", [core.kind, core.name, missing])
}
missing_labels = missing {
provided := {label | core.labels[label]}
required := {label | label := input.parameters.labels[_]}
missing := required - provided
}
You can optionally specify annotations and labels for the generated Constraint. This can be useful if you use Argo CD for deployment (see here).
# METADATA
# title: Required Labels
# description: >-
# This policy allows you to require certain labels are set on a resource.
# custom:
# annotations:
# "argocd.argoproj.io/sync-options": "SkipDryRunOnMissingResource=true"
...