Skip to content

Conftest

Conftest helps you write tests against structured configuration data. Using Conftest you can write tests for your Kubernetes configuration. Conftest uses the Rego language from Open Policy Agent for writing the assertions.

Here's a simple policy that checks whether a given container runs as root:

package main

deny[res] {
  input.kind == "Deployment"
  not input.spec.template.spec.securityContext.runAsNonRoot

  msg := "Containers must not run as root"

  res := {
    "msg": msg,
    "title": "Runs as root user"
  }
}

To integrate Conftest scanner change the value of the configAuditReports.scanner property to Conftest:

kubectl patch cm starboard -n <starboard_namespace> \
  --type merge \
  -p "$(cat <<EOF
{
  "data": {
    "configAuditReports.scanner": "Conftest"
  }
}
EOF
)"

Warning

Starboard does not ship with any default policies that can be used with Conftest plugin, therefore you have to add them manually.

In the following example, we'll use OPA polices provided by the AppShield project.

Start by cloning the AppShield repository and changing the current directory to the cloned repository:

git clone https://github.com/aquasecurity/appshield
cd appshield

Most of the Kubernetes policies defined by the AppShield project refer to OPA libraries called kubernetes.rego and utils.rego. You must add such libraries to the starboard-conftest-config ConfigMap along with the actual policies.

As an example, let's create the starboard-conftest-config ConfigMap with file_system_not_read_only.rego and uses_image_tag_latest.rego policies. Those two are very common checks performed by many other tools:

kubectl create configmap starboard-conftest-config -n <starboard_namespace> \
  --from-literal=conftest.imageRef=openpolicyagent/conftest:v0.25.0 \
  --from-file=conftest.policy.kubernetes.rego=kubernetes/lib/kubernetes.rego \
  --from-file=conftest.policy.utils.rego=kubernetes/lib/utils.rego \
  --from-file=conftest.policy.file_system_not_read_only.rego=kubernetes/policies/general/file_system_not_read_only.rego \
  --from-file=conftest.policy.uses_image_tag_latest.rego=kubernetes/policies/general/uses_image_tag_latest.rego

To test this setup out with Starboard CLI you can create the nginx Deployment with the latest nginx image and check its configuration:

kubectl create deployment nginx --image nginx
starboard scan configauditreports deployment/nginx

Finally, inspect the ConfigAuditReport to confirm that the Deployment is not compliant with test policies:

$ kubectl get configauditreport deployment-nginx -o jsonpath='{.report}' | jq
{
  "checks": [
    {
      "category": "Security",
      "checkID": "Root file system is not read-only",
      "message": "container nginx of deployment nginx in default namespace should set securityContext.readOnlyRootFilesystem to true",
      "severity": "DANGER",
      "success": false
    },
    {
      "category": "Security",
      "checkID": "Image tag \":latest\" used",
      "message": "container nginx of deployment nginx in default namespace should specify image tag",
      "severity": "DANGER",
      "success": false
    }
  ],
  "scanner": {
    "name": "Conftest",
    "vendor": "Open Policy Agent",
    "version": "v0.25.0"
  },
  "summary": {
    "dangerCount": 2,
    "passCount": 0,
    "warningCount": 0
  },
  "updateTimestamp": "2021-04-15T13:54:49Z"
}

Tip

The steps for configuring Conftest with Starboard CLI and Starboard Operator are the same except the namespace in which the starboard-conftest-config ConfigMap is created.

Settings

CONFIGMAP KEY DEFAULT DESCRIPTION
conftest.imageRef docker.io/openpolicyagent/conftest:v0.25.0 Conftest image reference
conftest.resources.requests.cpu 50m The minimum amount of CPU required to run Conftest scanner pod.
conftest.resources.requests.memory 50M The minimum amount of memory required to run Conftest scanner pod.
conftest.resources.limits.cpu 300m The maximum amount of CPU allowed to run Conftest scanner pod.
conftest.resources.limits.memory 300M The maximum amount of memory allowed to run Conftest scanner pod.