Compliance as code means expressing the technical parts of your controls as versioned, repeatable checks. Policy as code is the rule language and evaluation mechanism behind those checks. Neither term means that a passing infrastructure scan proves that an organization meets every requirement of SOC 2, HIPAA, or another framework. People, process, scope, and evidence still matter.
For infrastructure teams, the practical choice is where a check runs and who maintains it: static analysis in a pull request, a policy decision on a proposed plan, or a check against deployed resources. These approaches complement each other. A scanner can block a deployment when the pipeline treats a failure as a gate.
Checkov, OPA, Conftest, and Trivy Compared
The comparison below uses the same criteria for each tool: input, execution point, policy ownership, and the main boundary. It describes the documented open-source capabilities, not an independently measured performance benchmark. Review the linked documentation for the version you install.
| Tool | Input and execution point | Policy ownership | Useful fit | Main boundary |
|---|---|---|---|---|
| Checkov | IaC files and supported Terraform plan JSON; local checks or CI before apply | Built-in checks plus custom Python or YAML policies | Start with common IaC misconfiguration checks | CLI findings become a deployment gate only when your workflow enforces them |
| OPA | Structured input such as JSON; wherever an integration asks for a decision | Your Rego rules and supporting data | Organization-specific decisions across services or infrastructure | The caller supplies input and enforces the decision |
| Conftest | Structured configuration files, including YAML, JSON, and HCL; local checks or CI | Your Rego rules, using OPA | Test repository configuration with a small command-line workflow | You maintain the rules and connect failures to your release process |
| Trivy | Supported IaC files through trivy config; local checks or CI | Built-in misconfiguration checks plus custom checks | Add IaC checks to a broader security scanning workflow | Configuration checks and package vulnerability scanning answer different questions |
Checkov documents static analysis and custom checks. OPA separates policy decisions from enforcement, while Conftest packages Rego tests for configuration files. Trivy documents pre-deployment IaC misconfiguration scanning. None of these tools should be categorized as inherently post-deployment-only.
Where tfsec fits. tfsec is a Terraform static-analysis scanner. Its maintainers encourage users to move to Trivy, where they are concentrating development effort. It is not a live-cloud-only scanner. See the official tfsec-to-Trivy guidance.
Approach 1: Build Your Own Policy Checks
Custom policy-as-code gives you control over the rule and its exceptions. You can require approved regions, ownership tags, encryption, or a review from the right team. OPA evaluates the supplied data; your deployment system decides whether a denial stops the run.
The maintenance work is real. Someone must define the input schema, test passing and failing cases, version the policies, and own exceptions. Missing or unknown values need an explicit outcome; an absent field should not silently become evidence that a control passed.
Use this approach when organization-specific rules are important and a team can own them. Conftest is a useful entry point for testing structured configuration in CI. A larger OPA integration can reuse decisions across multiple systems, but it still needs an enforcement path.
Approach 2: Scan IaC Before Deployment and Live State Afterward
Checkov and Trivy can find common configuration weaknesses in a repository before resources are created. Put the scan in the pull request and make the relevant failures block the release. Define which checks matter, how an exception is approved, and where the result is retained.
A pre-deployment scan cannot prove that production still matches the reviewed code. Live-state checks are a separate layer for console changes, resources outside IaC, and conditions that change after release. Keep both views: what was proposed and what is running.
Approach 3: Compliance Built Into the Pipeline
In ops0, compliance checks sit alongside generated IaC and deployment review. The workflow connects policy results to the infrastructure change and its operational context. Review the compliance workflow to decide whether it fits the controls your team needs.
Built-in checks reduce the amount of policy you need to start with. They still require scope review, exception ownership, and evidence retention. A framework label is a mapping to evaluate; it is not a certification or a substitute for an auditor reviewing the wider control environment.
Worked Example: A Production Database Encryption Check
Illustrative lab example. The following input is a deliberately simplified record, not a Terraform plan schema, a customer result, or an ops0 deployment log. The technical control is narrow: a production database must have storage encryption enabled.
Save this normalized input as example.json. In a real integration, derive the value from the proposed resource configuration and validate that the environment, resource address, and encryption value are present and have the expected types.
{
"resource_address": "aws_db_instance.orders",
"environment": "production",
"storage_encrypted": false
}
Save this rule as policy/encryption.rego. It uses Rego v1 syntax supported by current OPA and Conftest. For this production record, a missing encryption field is treated like a false value.
package main
deny contains reason if {
input.environment == "production"
object.get(input, "storage_encrypted", false) != true
reason := sprintf("%s requires storage encryption", [input.resource_address])
}
conftest test example.json --policy policy
Expected lab behavior. The false value should produce a denial. Change it to true and rerun the check; this rule should no longer deny the record. Also test a missing field, an invalid type, and your input-validation failures before using a policy in a release gate. These are expected test cases, not measured results from a customer environment.
This single check does not cover key ownership, rotation, backups, access permissions, or whether an existing unencrypted database can be changed without replacement. Map each requirement to the right evidence and inspect the actual infrastructure plan before deciding how to remediate it.
The Hybrid Approach
Combine built-in checks for common misconfigurations with custom rules for your organization. Then check live resources for changes that bypassed the normal deployment workflow. The important boundary is between a finding and an enforced decision, not between a tool with or without an AI label.
What Auditors Need to Trace
Retain the resource or plan that was checked, the policy version, the result, the time, the reviewer, and any approved exception. Tie the check to the deployment outcome. Record a failed gate as a failed gate; do not label a proposed or hypothetical control as a successful production result.
Choose the approach that lets your team explain a specific change: which control applied, what evidence was evaluated, who approved an exception, and whether the deployed resource still meets the intended setting.
For a product workflow, explore ops0 compliance and policy enforcement. For the wider review and evidence process, see infrastructure audit. Start with one real control and a passing, failing, and missing-input test before expanding the policy library.
Evidence Record Template
Illustrative record template, not an observed deployment. Fill each field from the actual check and approval workflow.
Change: <reviewed commit or plan reference>
Control and policy version: <versioned check>
Result: <actual pass, fail, or error>
Reviewer or exception owner: <recorded identity>
Evidence: <input, check output, approval, deployment result>
What is compliance as code?
Compliance as code expresses security and regulatory controls as repeatable checks that can run during infrastructure review, deployment, and audit workflows.
Can IaC scanning stop a deployment?
Yes. Checkov and Trivy can run before deployment. A scanner stops a release only when the pipeline enforces its result as a gate; live-state checks are still needed for later changes.
How does ops0 support compliance workflows?
ops0 connects compliance checks to generated IaC, deployment workflows, policy gates, drift context, and audit evidence.
- What is Checkov?: Checkov. Static analysis, supported IaC types, and custom policy capabilities.
- Terraform Plan Scanning: Checkov. Terraform plan JSON input and its scanning boundaries.
- Open Policy Agent documentation: Open Policy Agent. Structured input, Rego, and separation of decisions from enforcement.
- Conftest documentation: Conftest. Configuration tests, Rego rules, and the test command used by the illustrative example.
- Misconfiguration Scanning: Aqua Security / Trivy. IaC scanning, custom checks, and the trivy config command.
- tfsec to Trivy migration: Aqua Security. tfsec static-analysis scope and maintainer migration guidance.