Konstraint is a tool for converting Open Policy Agent policies written in rego into ConstraintTemplates and Constraints for Gatekeeper. In Open Policy Agent: Introduction to Gatekeeper, we learned how to deploy Gatekeeper and create ConstraintTemplates and Constraints. Then in Open Policy Agent: Unit Testing Gatekeeper Policies, we copied rego from ConstraintTemplates to validate syntax and unit test policies.
This process left us with duplication of rego because it existed in the ConstraintTemplate and rego files. Konstraint is the missing piece. Konstraint can be used in a build process to convert rego into ConstraintTemplates and Constraints preventing us from having to duplicate code.
Download konstraint
konstraint can be downloaded from Konstraint’s releases page. I’ll be using version v0.9.2.
To install on Linux, for example, run:
|
|
To verify konstraint is installed correctly, run:
|
|
and the output should be:
konsstraint version v0.9.2
Project setup
We’ll use the existing structure from the previous post. Our project structure will look like:
~/policies
└── image-tag
├── src.rego
└── src_test.rego
For this post, we’ll ignore the contents of src_test.rego as Konstraint ignores files that end
with _test.rego.
We’ll start with the rego code that did not have a parameter, so src.rego is:
|
|
Use Konstraint to create ConstraintTemplates and Constraints
With our project setup, now we can run:
|
|
Our project structure will then look like:
policies
└── image-tag
├── constraint.yaml
├── src.rego
├── src_test.rego
└── template.yaml
Konstraint created two files, constraint.yaml and template.yaml.
template.yaml looks like:
|
|
Looks like what we created in Open Policy Agent: Introduction to Gatekeeper!
And constraint.yaml looks like:
|
|
This Constraint works as-is but is different than what we did before. enforcementAction is omitted,
meaning the default of deny is in effect. The match is also missing for this Constraint, so
Gatekeeper will execute this policy against all resources.
Fortunately, Konstraint has a solution for this. We can add comments to our rego to set these options.
Update src.rego to look like:
|
|
Re-run:
|
|
and constraint.yaml will now look like:
|
|
Perfect. Now we’re able to only write rego code in one place, src.rego, and generate
ConstraintTemplates and Constraints using Konstraint.
Use Konstraint to create parameterized ConstraintTemplates
Now, let’s update our src.rego to use a parameter.
|
|
Go ahead and delete the template.yaml and constraint.yaml files. Then re-run:
|
|
Note:
konstraint createwill verify each parameter referenced in rego is described with a@parametercomment and vice versa.
Notice now that only template.yaml is created, which looks like:
|
|
When Konstraint detects a parameterized rego, Konstraint will skip creating a constraint.yaml file.
It is up to the user to manually create a constraint.yaml file as Konstraint doesn’t know the
parameters.
A bit of a bummer, but we still get the incredible benefit of the automatic creation of ConstraintTemplates.
Note:
@enforcementand@kindscomments are both ignored by Konstraint when the policy is parameterized, so no need to specify them.
Use Konstraint to build documentation
On top of creating ConstraintTemplate and Constraints (in some cases), Konstraint can generate policy documentation.
Once again, update src.rego to be:
|
|
and then run:
|
|
Konstraint will create a file at ~/policies.md with the policy’s title, description, the
rego code itself, enforcement kind, and any kinds/parameters specified.
More opa tools?
We’ve now tackled Gatekeeper, opa, and Konstraint. Konstraint is relatively new, but I look forward to future features it adds. Know any more tools to help with writing policies? Or better ways to use these tools? Please let me know on LinkedIn.