All integrations

Conftest Integration with DefectDojo

Conftest Integration with DefectDojo

Conftest is an open source tool for testing structured configuration data against policies written in Rego, the policy language of Open Policy Agent (OPA). It is maintained in the Open Policy Agent GitHub organization and evaluates Kubernetes manifests, Terraform code, Dockerfiles, CI pipeline definitions, and other configuration files. Conftest ships no built-in rule set: you write the policies, and it reports which deny and warn rules each file violated. With --output json it writes a report DefectDojo can import.

Conftest Integration with DefectDojo

We use Conftest to enforce our own configuration standards in CI, and we import its JSON output into DefectDojo so policy violations get tracked like any other finding. A failed Conftest step tells one developer that one build broke a rule. In DefectDojo, each violation becomes a Finding on the Asset that owns the repository, with its severity taken from whether the rule was a deny or a warn, and it stays open until a later run of the same policies comes back clean.

Why Conftest Matters

Configuration is code, and most cloud and cluster misconfigurations start in a file someone committed.

  • Policies are yours. Conftest enforces your organization's actual requirements, such as resource limits, approved registries, or required labels, not a generic baseline.
  • It is format-agnostic, so one policy toolchain covers Kubernetes, Terraform, Dockerfiles, and pipeline config.
  • Rego is the same language used by OPA admission control, so the rules you test in CI can match what you enforce at runtime.
  • It separates hard failures (deny) from advisories (warn).
  • On its own, Conftest reports one run at a time. It cannot tell you which violations are new, which have been open for weeks, or which teams own them.

Advantages of This Integration

What running Conftest through DefectDojo adds:

  • Severity from your policy intent. Violations of deny rules import as High and violations of warn rules as Medium, and the description records which kind it was.
  • Nothing that isn't a finding. Results a policy explicitly allowed through an exception rule, and policies that were skipped, are not imported. Passing rules are only a count in Conftest output, so they are not imported either.
  • Your metadata preserved. Anything a policy attaches to a result's metadata, such as its own severity or a control ID, is written into the description.
  • Deduplication across runs. Conftest has no dedicated hashcode entry, so DefectDojo uses its legacy field set (title, CWE, line, file path, description). In practice that means the same rule message on the same file is recognized as one Finding.
  • A remediation lifecycle. Reimporting into the same Test mitigates violations that were fixed and adds new ones.
  • Shared workflow. Policy findings can be assigned, risk-accepted with an expiration date, pushed to Jira, and reported next to scanner findings for the same Asset.

How This Integration Works

DefectDojo imports Conftest output with the Conftest Scan scan type. The report must be the JSON array Conftest writes, with one object per checked file.

1. Produce a JSON report.

conftest test --output json --policy ./policy ./manifests > conftest.json

Conftest exits non-zero when a deny rule matches. If your CI step fails the build on a non-zero exit, make sure the upload step still runs (for example, as an always-run step), or the report never reaches DefectDojo.

2. Import it. In the UI, open the Engagement, choose Import Scan Results, select Conftest Scan, and upload the file. For automation, use the import API, available in Community Edition and DefectDojo Pro:

curl "https://YOUR_INSTANCE/api/v2/import-scan/" 
  -H "Authorization: Token $DD_API_TOKEN" 
  -F "scan_type=Conftest Scan" 
  -F "file=@conftest.json" 
  -F "product_name=platform-manifests" 
  -F "engagement_name=Policy Checks" 
  -F "auto_create_context=true"

DefectDojo Pro users can run the same import with Universal Importer:

universal-importer import 
  --defectdojo-url "https://YOUR_INSTANCE.cloud.defectdojo.com/" 
  --scan-type "Conftest Scan" 
  --report-path "./conftest.json" 
  --product-name "platform-manifests" 
  --engagement-name "Policy Checks" 
  --auto-create-context

3. Reimport on each run. Send later reports to /api/v2/reimport-scan/ against the same Test so the Test reflects the current state of the repository's configuration.

A clean file appears in the report with only its filename, namespace, and a success count. The failures and warnings keys are absent, and the parser handles that, so a fully compliant run imports as zero findings rather than failing.

Data Granularity: What Gets Imported

DefectDojo Field Source in Conftest Report Notes
Title msg of the result The rule's own message; Rego deny and warn rules have no ID
Severity Which array the result is in failures (deny) High, warnings (warn) Medium
Description Message, result kind, namespace, query, file, metadata All extra metadata keys from the policy are listed
File Path filename The configuration file evaluated
Line Not available Conftest does not report a line number
Vulnerability ID from tool metadata.query For example data.main.deny; names the rule set, not one rule
Finding type Static All findings are marked static
Not imported exceptions, skipped, successes Allowed exceptions, unevaluated policies, and the pass count
Deduplication Hashcode (legacy fields) title, cwe, line, file_path, description

Use Cases

Kubernetes manifest checks in CI: A pipeline runs Conftest against rendered manifests for every service and reimports into a Test per repository. Platform engineers see which services still lack resource limits or run as root, and the list shrinks as teams fix them.

Terraform plan review: Teams run Conftest against a JSON Terraform plan before apply. Deny rules covering public storage or open security groups import as High, so they fall under a tighter SLA than advisory warn rules.

Rolling out a new rule: A security team adds a policy as a warn rule first. DefectDojo shows how many files fail it as Medium findings, and once teams have had time to fix them, the rule is promoted to deny and future violations arrive as High.

Recording accepted deviations: Where a policy author has written an exception rule, nothing is imported. Where a team needs a temporary exception that is not in policy, risk acceptance in DefectDojo records the reason and an expiration date.

Operational Tips

  • Write clear, specific msg strings, and include the resource name in them. The message is the Finding title and part of the dedupe hash, so a generic message on many resources in one file collapses them.
  • Avoid putting volatile values (timestamps, run IDs) in messages or metadata, since the description is also hashed and would make every run look new.
  • Attach your own severity or control fields to rule metadata if you need finer grading. They appear in the description, where triage can use them.
  • Use one Test per repository or policy bundle and reimport into it, so fixed files close their findings.
  • Make the upload step run even when Conftest exits non-zero, otherwise you only ever import clean runs.
  • Tag imports with the policy bundle version (for example tags=policy-v12) so changes in finding counts can be tied to policy changes.