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"]

Resources