Manageing configuration tends to come down to maintaining loads of yaml or json files which can get messy pretty quickly. To help ensure some standards it's important to lint even these files.
In Kubernetes there are some nice projects to that end, such as KubeScore and Kubelint, but they aren't really customizable in a way which allows you to validate the configuration given a certain context. This is where Conftest and Rego come in to play.
In this post I'd like to show some tips and trips using a working example. The code can be found on Gitlab, but if you'd like to play around with the policies, feel free to clone it and run it locally (Nb. you will need Docker running locally in order to do that).
Conftest can be run as follows:
$ ./bin/conftest test --all-namespaces --data policy/data/dev dev
What this does test the policies in the policy
directory using the --data
in policy/data/dev
, in this case there is a file stage.yaml
with the following contents:
---
stage:
name: dev
allowed_kinds:
- Deployment
- Service
required_labels:
"Deployment":
- app
Conftest's documentation on --data says that stage
will be import
'able as follows:
import data.stage
There are a couple of example OPA Policies in the policy directory of the example-project, but here is one I'd like to showcase since it has a couple of features:
package k8s.kind.deployment
import data.stage
deny_deployment_missing_label[msg] {
is_deployment
name := input.metadata.name
all({
required | required := data.stage.required_labels["Deployment"][_]
input.metadata.labels[ required ]
})
msg := sprintf("Deployment %s must be qualified with a label: %s", [ name , data.stage.required_labels["Deployment"] ])
}
is_deployment {
input.kind == "Deployment"
}
This policy applies to any configuration file which is of kind
"Deployment". It then iterates the required
labels from the stage-data
and ensures they are present.
Given this configuration and this rules, if a deployment manifest doesn't have a label "app" you can expect a failure message similar to:
FAIL - dev/app/fails-deployment-missing-label.yaml - k8s.kind.deployment - Deployment conftest-example must be qualified with a label: ["app"]