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
:
TRIVY_OPERATOR_NAMESPACE=<TRIVY_OPERATOR_NAMESPACE>
kubectl patch cm starboard -n $TRIVY_OPERATOR_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:
TRIVY_OPERATOR_NAMESPACE=<TRIVY_OPERATOR_NAMESPACE>
kubectl create configmap starboard-conftest-config --namespace $TRIVY_OPERATOR_NAMESPACE \
--from-literal=conftest.imageRef=openpolicyagent/conftest:v0.30.0 \
--from-file=conftest.library.kubernetes.rego=kubernetes/lib/kubernetes.rego \
--from-file=conftest.library.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 \
--from-literal=conftest.policy.file_system_not_read_only.kinds=Workload \
--from-literal=conftest.policy.uses_image_tag_latest.kinds=Workload
Tip
For the operator the Helm install command may look as follows.
TRIVY_OPERATOR_NAMESPACE=<TRIVY_OPERATOR_NAMESPACE>
helm install starboard-operator aqua/starboard-operator \
--namespace $TRIVY_OPERATOR_NAMESPACE --create-namespace \
--set="targetNamespaces=default" \
--set="starboard.configAuditReportsPlugin=Conftest" \
--set-file="conftest.library.kubernetes\.rego=kubernetes/lib/kubernetes.rego" \
--set-file="conftest.library.utils\.rego=kubernetes/lib/utils.rego" \
--set-file="conftest.policy.file_system_not_read_only.rego=kubernetes/policies/general/file_system_not_read_only.rego" \
--set-file="conftest.policy.uses_image_tag_latest.rego=kubernetes/policies/general/uses_image_tag_latest.rego" \
--set-string="conftest.policy.file_system_not_read_only.kinds=Workload" \
--set-string="conftest.policy.uses_image_tag_latest.kinds=Workload"
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:
$ starboard get configauditreports deployment/nginx -o yaml
apiVersion: aquasecurity.github.io/v1alpha1
kind: ConfigAuditReport
metadata:
creationTimestamp: "2021-10-27T12:42:20Z"
generation: 1
labels:
plugin-config-hash: 5d5f578dd6
resource-spec-hash: 7d48b6dfcf
starboard.resource.kind: ReplicaSet
starboard.resource.name: nginx-6799fc88d8
starboard.resource.namespace: default
name: replicaset-nginx-6799fc88d8
namespace: default
ownerReferences:
- apiVersion: apps/v1
blockOwnerDeletion: false
controller: true
kind: ReplicaSet
name: nginx-6799fc88d8
uid: cdfd93d7-9419-4e2d-a120-107bed2f3d57
resourceVersion: "88048"
uid: 362d5b06-65a5-4925-bf96-19d23f088e0c
report:
updateTimestamp: "2021-10-27T12:42:20Z"
scanner:
name: Conftest
vendor: Open Policy Agent
version: v0.25.0
summary:
dangerCount: 2
passCount: 0
warningCount: 0
checks:
- category: Security
checkID: Root file system is not read-only
message: Container 'nginx' of ReplicaSet 'nginx-6799fc88d8' should set 'securityContext.readOnlyRootFilesystem'
to true
severity: danger
success: false
- category: Security
checkID: Image tag ':latest' used
message: Container 'nginx' of ReplicaSet 'nginx-6799fc88d8' should specify an
image tag
severity: danger
success: false
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.30.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. |
conftest.library.<name>.rego |
N/A | Rego library with helper functions |
conftest.policy.<name>.rego |
N/A | Rego policy with the specified name |
conftest.policy.<name>.kinds |
N/A | A comma-separated list of Kubernetes kinds applicable to the policy with a given name. You can use Workload or * as special kinds to represent any Kubernetes workload or any object. |