Options

Configuration

Options for Conftest can be configured on the command line as flag arguments, environment variables, or a configuration file.

When multiple configuration sources are present, Conftest will process the configuration values in the following order:

  1. Flag Arguments
  2. Environment Variables
  3. Configuration File

When using environment variables, the environment variable should be the same name as the flag, prefixed with CONFTEST_. For example, to set the policy directory, the environment variable would be CONFTEST_POLICY.

When using a configuration file, the configuration file should be in the working directory for Conftest and named conftest.toml. An example can be found below:

# You can override the directory in which to store and look for policies
policy = "tests"

# You can override the namespace which to search for rules
namespace = "conftest"

--combine

This flag introduces BREAKING CHANGES in how Conftest provides input to rego policies. However, you may find it useful to use as it allows you to compare multiple values from different configurations simultaneously.

The --combine flag combines files into one input data structure. The structure is an array where each element is a map with two keys: a path key with the relative file path of the file being evaluated and a contents key containing the actual document.

Let's try it!

Save the following as policy/combine.rego:

package main

deny[msg] {
  input[i].contents.kind == "Deployment"

  deployment := input[i].contents

  not service_selects_app(deployment.spec.selector.matchLabels.app)

  msg := sprintf("Deployment %v with selector %v does not match any Services", [deployment.metadata.name, deployment.spec.selector.matchLabels])
}

service_selects_app(app) {
  input[service].contents.kind == "Service"
  input[service].contents.spec.selector.app == app
}

Save the following as manifests.yaml:

apiVersion: v1
kind: Service
metadata:
  name: hello-kubernetes
spec:
  type: LoadBalancer
  ports:
  - port: 80
    targetPort: 8080
  selector:
    app: goodbye-kubernetes
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-kubernetes
spec:
  replicas: 3
  selector:
    matchLabels:
      app: hello-kubernetes

With the above file created, run the following command:

$ conftest test manifests.yaml --combine

FAIL - Combined - Deployment hello-kubernetes has selector hello-kubernetes that does not match any Services

1 test, 0 passed, 0 warnings, 1 failure, 0 exceptions

It is also possible to pass in multiple files. Creating .yaml file for both the Service and the Deployment.

$ conftest test service.yaml deployment.yaml --combine

FAIL - Combined - Deployment hello-kubernetes has selector hello-kubernetes that does not match any Services

1 test, 0 passed, 0 warnings, 1 failure, 0 exceptions

This is just the tip of the iceberg. Now you can ensure that duplicate values match across the entirety of your configuration files.

--config-file (-c)

Sets the location of the Conftest configuration file

For example:

conftest -c examples/configfile/conftest.toml test -p examples/configfile/test examples/configfile/deployment.yaml

--data

Sometimes policies require additional data in order to determine an answer.

For example, an allowed list of resources that can be created. Instead of hardcoding this information inside of your policy, conftest allows passing paths to data files with the --data flag.

conftest test -p examples/data/policy -d examples/data/exclusions examples/data/service.yaml

The paths at the flag are recursively searched for JSON and YAML files. Data can be imported as follows:

Given the following yaml file:

services:
  ports:
  - 22

This can be imported into your policy:

import data.services

ports := services.ports

--fail-on-warn

Policies can either be categorized as a warning (using the warn rule) or a failure (using the deny or violation rules). By default, Conftest only returns an exit code of 1 when a policy has failed.

The --fail-on-warn flag changes this behavior to the following:

  • Exit code of 0: No failures or warnings.
  • Exit code of 1: No failures, but there exists at least one warning.
  • Exit code of 2: At least one failure.

--ignore

When a directory is given as an input, Conftest will recursively find, and test all files that it supports. To ignore certain directories or files, the --ignore flag takes a regexp pattern that will ignore directories and files that match the pattern.

Here are some examples:

conftest test -p examples/test/ test/ --ignore="parent/"
conftest test -p examples/test/ test/ --ignore="child/"
conftest test -p examples/test/ test/ --ignore=".*.yaml"
conftest test -p examples/test/ test/ --ignore=".*.cue|.*.yaml"

--output

The output of Conftest can be configured using the --output flag (-o).

As of today Conftest supports the following output types:

  • Plaintext --output=stdout
  • JSON: --output=json
  • TAP: --output=tap
  • Table --output=table
  • JUnit --output=junit
  • GitHub --output=github
  • AzureDevOps --output=azuredevops

Plaintext

$ conftest test -p examples/kubernetes/policy examples/kubernetes/deployment.yaml
FAIL - examples/kubernetes/deployment.yaml - hello-kubernetes must include Kubernetes recommended labels: https://kubernetes.io/docs/concepts/overview/working-with-objects/common-labels/#labels     
FAIL - examples/kubernetes/deployment.yaml - Containers must not run as root in Deployment hello-kubernetes
FAIL - examples/kubernetes/deployment.yaml - Deployment hello-kubernetes must provide app/release labels for pod selectors
FAIL - examples/kubernetes/deployment.yaml - Found deployment hello-kubernetes but deployments are not allowed

5 tests, 1 passed, 0 warnings, 4 failures, 0 exceptions

JSON

$ conftest test -o json -p examples/kubernetes/policy examples/kubernetes/deployment.yaml
[
        {
                "filename": "examples/kubernetes/deployment.yaml",
                "successes": 1,
                "failures": [
                        {
                                "msg": "Containers must not run as root in Deployment hello-kubernetes"
                        },
                        {
                                "msg": "Deployment hello-kubernetes must provide app/release labels for pod selectors"
                        },
                        {
                                "msg": "hello-kubernetes must include Kubernetes recommended labels: https://kubernetes.io/docs/concepts/overview/working-with-objects/common-labels/#labels"
                        },
                        {
                                "msg": "Found deployment hello-kubernetes but deployments are not allowed",
                                "metadata": {
                                        "details": {}
                                }
                        }
                ]
        }
]

TAP

$ conftest test -o tap -p examples/kubernetes/policy examples/kubernetes/deployment.yaml
1..5
not ok 1 - examples/kubernetes/deployment.yaml - Found deployment hello-kubernetes but deployments are not allowed
not ok 2 - examples/kubernetes/deployment.yaml - Containers must not run as root in Deployment hello-kubernetes
not ok 3 - examples/kubernetes/deployment.yaml - Deployment hello-kubernetes must provide app/release labels for pod selectors
not ok 4 - examples/kubernetes/deployment.yaml - hello-kubernetes must include Kubernetes recommended labels: https://kubernetes.io/docs/concepts/overview/working-with-objects/common-labels/#labels
# successes
ok 5 - examples/kubernetes/deployment.yaml -

Table

$ conftest test -p examples/kubernetes/policy examples/kubernetes/service.yaml -o table
+---------+----------------------------------+--------------------------------+
| RESULT  |               FILE               |            MESSAGE             |
+---------+----------------------------------+--------------------------------+
| success | examples/kubernetes/service.yaml |                                |
| success | examples/kubernetes/service.yaml |                                |
| success | examples/kubernetes/service.yaml |                                |
| success | examples/kubernetes/service.yaml |                                |
| warning | examples/kubernetes/service.yaml | Found service hello-kubernetes |
|         |                                  | but services are not allowed   |
+---------+----------------------------------+--------------------------------+

JUnit

$ conftest test -p examples/kubernetes/policy examples/kubernetes/service.yaml -o junit
<?xml version="1.0" encoding="UTF-8"?>
<testsuites>
        <testsuite tests="5" failures="4" time="0.000" name="conftest">
                <properties>
                        <property name="go.version" value="go1.15.1"></property>
                </properties>
                <testcase classname="conftest" name="examples/kubernetes/deployment.yaml - Containers must not run as root in Deployment hello-kubernetes" time="0.000">
                        <failure message="Failed" type="">Containers must not run as root in Deployment hello-kubernetes</failure>
                </testcase>
                <testcase classname="conftest" name="examples/kubernetes/deployment.yaml - Deployment hello-kubernetes must provide app/release labels for pod selectors" time="0.000">
                        <failure message="Failed" type="">Deployment hello-kubernetes must provide app/release labels for pod selectors</failure>
                </testcase>
                <testcase classname="conftest" name="examples/kubernetes/deployment.yaml - hello-kubernetes must include Kubernetes recommended labels: https://kubernetes.io/docs/concepts/overview/working-with-objects/common-labels/#labels" time="0.000">
                        <failure message="Failed" type="">hello-kubernetes must include Kubernetes recommended labels: https://kubernetes.io/docs/concepts/overview/working-with-objects/common-labels/#labels</failure>
                </testcase>
                <testcase classname="conftest" name="examples/kubernetes/deployment.yaml - Found deployment hello-kubernetes but deployments are not allowed" time="0.000">
                        <failure message="Failed" type="">Found deployment hello-kubernetes but deployments are not allowed</failure>
                </testcase>
                <testcase classname="conftest" name="examples/kubernetes/deployment.yaml - " time="0.000"></testcase>
        </testsu

GitHub

$ conftest test -o github -p examples/kubernetes/policy examples/kubernetes/deployment.yaml
::group::Testing 'examples/kubernetes/deployment.yaml' against 5 policies in namespace 'main'
::error file=examples/kubernetes/deployment.yaml::Containers must not run as root in Deployment hello-kubernetes
::error file=examples/kubernetes/deployment.yaml::Deployment hello-kubernetes must provide app/release labels for pod selectors
::error file=examples/kubernetes/deployment.yaml::hello-kubernetes must include Kubernetes recommended labels: https://kubernetes.io/docs/concepts/overview/working-with-objects/common-labels/#labels
::error file=examples/kubernetes/deployment.yaml::Found deployment hello-kubernetes but deployments are not allowed
success file=examples/kubernetes/deployment.yaml 1
::endgroup::
5 tests, 1 passed, 0 warnings, 4 failures, 0 exceptions

Use Conftest directly to check incoming Pull Requests in GitHub:

---
name: Conftest

on:
  pull_request:
    branches: 
      - main

jobs:
  conftest:
    runs-on: ubuntu-latest
    container: openpolicyagent/conftest:latest
    steps:
      - name: Code checkout
        uses: actions/checkout@v3
      - name: Validate Kubernetes policy
        run: |
          conftest test -o github -p examples/kubernetes/policy examples/kubernetes/deployment.yaml

Azure DevOps

$ conftest test -o azuredevops -p examples/kubernetes/policy examples/kubernetes/deployment.yaml
##[section]Testing 'examples/kubernetes/deployment.yaml' against 5 policies in namespace 'main'
##[group]See conftest results
##vso[task.logissue type=error] file=examples/kubernetes/deployment.yaml --> Containers must not run as root in Deployment hello-kubernetes
##vso[task.logissue type=error] file=examples/kubernetes/deployment.yaml --> Deployment hello-kubernetes must provide app/release labels for pod selectors
##vso[task.logissue type=error] file=examples/kubernetes/deployment.yaml --> hello-kubernetes must include Kubernetes recommended labels: https://kubernetes.io/docs/concepts/overview/working-with-objects/common-labels/#labels
##vso[task.logissue type=error] file=examples/kubernetes/deployment.yaml --> Found deployment hello-kubernetes but deployments are not allowed
success file=examples/kubernetes/deployment.yaml 1
##[endgroup]
5 tests, 1 passed, 0 warnings, 4 failures, 0 exceptions

--parser

Conftest normally detects which parser to used based on the file extension of the file, even when multiple input files are passed in. However, it is possible force a specific parser to be used with the --parser flag.

For the available parsers, take a look at parsers.

For instance:

$ conftest test -p examples/hcl1/policy examples/hcl1/gke.tf --parser hcl2

2 tests, 2 passed, 0 warnings, 0 failures, 0 exceptions

--policy

Conftest will, by default, look for policies in the policy folder. This can be changed with the --policy (or -p) flag.

This flag can also be repeated, if you have multiple directories with policy files. For example one with organization-wide policies, and another one with team-specific policies. Keep in mind when using multiple directories that the rules are treated as if they had all been read from the same directory, so make sure any rules sharing the same name are compatible.

Read rules from the policy directory (default):

$ conftest test files/

Read rules from the my-policies directory:

$ conftest test -p my-policies files/

Reads rules from the my-policies and org-policies directories:

$ conftest test -p my-policies -p org-policies files/