Skip to main content
RunBook Academy

TerraformXXIII · Policy as CodeProduction Terraform

Policy Tools: Sentinel, OPA, Trivy, Checkov, tfsec

Intermediate⏱ ~16 minbash

What you'll learn

  • Distinguish the three layers: plan-time, static, and IaC scanning
  • Compare Sentinel, OPA / Conftest, Trivy, Checkov, tfsec on cost, lock-in, and language
  • Pick the right primary tool for a given team profile
  • Configure each tool on a representative project

Prerequisites

None — start here.

Verified against Terraform CLI 1.9.x · OpenTofu 1.7.x · HCL 2.0 · bpg/proxmox provider 0.66+ · hashicorp/local provider 2.5+ · hashicorp/null provider 3.2+ · hashicorp/random provider 3.6+ · hashicorp/http provider 3.4+ · Ubuntu 24.04 LTS · Debian 12 (Bookworm) · 2026-08-13

Not yet marked complete on this device.

Five tools show up in 2026 conversations about Terraform policy: HashiCorp Sentinel, Open Policy Agent (OPA) with Conftest, Aqua tfsec, Bridgecrew / Checkov, and Trivy. They look similar from a distance — all of them can stop a bad plan — and they disagree about almost everything else: where they run, what they evaluate against, what language the rules are written in, and how they ship. Picking the wrong primary tool is expensive to undo. Picking the right one is mostly a matter of asking the right questions.

Three layers, not five tools

The five names collapse into three layers of evaluation:

Layer           Evaluates          Tools
--------------------------------------------------
Plan-time       The plan JSON /    Sentinel, OPA / Conftest
                Sentinel import
Static          The HCL on disk    tfsec, Checkov
IaC scan        The HCL plus the   Trivy
                provider schema

A mature policy stack uses tools at more than one layer. Plan-time catches what the plan would do; static catches what the developer wrote before the plan is even run; IaC scanning adds vulnerability databases and provider-schema awareness on top of static analysis. The two layers are not redundant. Static can be wrong about what the plan will do (because the plan involves variable interpolation that static cannot see); plan-time cannot run on a 200-resource PR in a sensible time. The defence is in the depth.

HashiCorp Sentinel

Sentinel is HashiCorp’s policy-as-code language. It runs inside Terraform Cloud (and Terraform Enterprise). Rules are written in a Java-like syntax, imported against a typed view of the plan (tfplan/v2), and gated by the run workflow.

# Inside the Terraform Cloud workspace
sentinel test
PASS - aws-region-whitelist.sentinel
PASS - required-tags.sentinel
PASS - 2 policies, 0 failures

Where it wins. It is the only tool that runs inside the managed apply pipeline with a typed view of the plan and a first-class enforcement point. If the shop is on Terraform Cloud, Sentinel is zero infrastructure to run and zero glue to maintain.

Where it loses. Lock-in: the rule set does not move to local Terraform or OpenTofu without rewriting. The syntax is its own language, and the rule set is not portable to OPA. Sentinel is also managed-only in the form that hooks into the apply; community forks exist for local runs but are not production-grade.

Open Policy Agent (OPA) and Conftest

OPA is the open-source policy engine; Conftest is the wrapper that runs OPA rules against structured configuration files (JSON, YAML, HCL via a shim). Rules are written in Rego.

package terraform.encryption

deny[msg] {
  rc := input.resource_changes[_]
  rc.type == "aws_s3_bucket"
  not rc.change.after.server_side_encryption_configuration
  msg := sprintf("%s has no server-side encryption", [rc.address])
}
terraform show -json plan.tfplan > plan.json
conftest test plan.json --policy policy/
FAIL - plan.json - aws_s3_bucket.web has no server-side encryption
3 tests, 2 passed, 1 failure

Where it wins. Open source, runs anywhere, and integrates into CI pipelines with a single binary. Rego is documented and stable. Rules written in Rego apply to Kubernetes, Terraform plans, Dockerfile, and every other structured config the team touches. The same rule runs against Kubernetes admission control without rewriting.

Where it loses. The “plan as JSON” workflow requires terraform show -json plumbing in CI. The rule set has to be written and maintained by the team — there is no managed library of policies. Rego’s learning curve is real, particularly for engineers whose background is imperative languages.

Aqua tfsec

tfsec runs static analysis against the HCL on disk. It does not see the plan; it sees the configuration.

tfsec .
Result #1 ID: AWS002
  [aws_s3_bucket] Bucket is missing encryption configuration
  Location: main.tf: 12-18
  1 | resource "aws_s3_bucket" "web" {
  ...

Where it wins. Fast. Runs in pre-commit. The rule set is broad and updated frequently. Catches obvious misconfigurations before the plan is generated.

Where it loses. As of 2024 Aqua announced tfsec was moving into Trivy; new investment is in Trivy’s IaC scanner. Tools that depend on tfsec’s rule catalogue will see the migration happen regardless of whether the team chooses to ride along. Static-only — does not see plan interpolation. False positives on dynamic constructs (variables, conditionals).

Checkov

Bridgecrew’s Checkov is a static analyser with a heavy emphasis on the CIS and CIS-equivalent benchmark rulesets. It also has a plan-time mode (--framework terraform_plan).

checkov -d .
Check: CKV_AWS_18: "Ensure the S3 bucket has access logging"
  FAILED for resource: aws_s3_bucket.web
Check: CKV_AWS_19: "Ensure the S3 bucket has encryption"
  PASSED
Passed: 14, Failed: 3

Where it wins. The rule set is benchmark-mapped. For regulated workloads (PCI, HIPAA, ISO 27001) the rules are auditable against the source standard. Checkov’s graph-based analysis catches some property-graph issues that line-by-line tools miss.

Where it loses. Larger dependency tree than tfsec; the first-run experience downloads several frameworks. Some checks produce noise in pure-IaC scans (e.g. checks designed for Kubernetes that incidentally trip on Terraform kubernetes resources). Heavier than tfsec.

Trivy (mis Trivy IaC)

Trivy is the vulnerability scanner that broadened into IaC. The IaC layer covers Terraform plan output and the HCL on disk.

trivy config .
aws_s3_bucket.web (main.tf:12)
  Severity: HIGH
  ID: AVD-AWS-0088
  Description: S3 encryption not enabled
  Recommendation: Enable server-side encryption

Where it wins. Single tool for image scanning, filesystem scanning, and IaC scanning. CI integration is one binary call. The rule catalogue absorbs tfsec over time, which reduces the number of tools the team maintains.

Where it loses. Plan-time enforcement requires the IaC mode against a rendered plan. Rego-style custom policy is not the focus; new rules come from the catalogue, not from in-house authorship. For custom organisational policy the team still needs Sentinel or OPA.

Comparison matrix

ToolLayerLanguageOSSPlan-time gateBest for
SentinelPlanSentinelNo (BSL)Yes (TFC)HashiCorp-managed shops
OPA / ConftestPlanRegoYesYes (CI)Multi-tool policy surface
tfsecStaticRego (rules)YesNoPre-commit, fast feedback
CheckovStaticPython (rules)YesYes (plan mode)Regulated workloads
TrivyIaCGo (rules)YesYes (IaC mode)Consolidated security CI

The right choice per team profile

A few real choices a sysadmin team faces in 2026:

Team A: 5 engineers, 3 workspaces, Terraform Cloud already bought. Use Sentinel. The decision to use plan-time policy has already been made; the language choice is forced. The team writes the rule set, which is small (under 50 rules for most shops). Custom rules are written as needed.

Team B: 25 engineers, 12 workspaces, self-hosted CI, no TFC. Use OPA / Conftest for plan-time policy plus tfsec (or the Trivy IaC scanner) in pre-commit. The rules live in the same repository as the infrastructure code. Conftest runs in the CI step that gates the merge.

Team C: regulated workload, 50 engineers, multiple clouds. Use Checkov as the static baseline (benchmarks map to the auditor’s checklist) plus OPA / Conftest for organisational custom rules. Trivy is added if the team does not already have an image scanner.

Team D: 80 engineers, Kubernetes plus Terraform. Use OPA / Conftest for both. The same Rego bundle runs against Terraform plans in CI and against Kubernetes admission controllers via Gatekeeper. The rule authoring is in one language. The team runs Trivy separately for the rest of the scanner workload.

Validation

The validation is different per tool, but the principle is the same: a passing run for a known-good plan, and a failing run for a known-bad plan.

conftest test plan.json --policy policy/
5 tests, 5 passed, 0 warnings, 0 failures
tfsec .
OK - no issues detected
2 files scanned

For Sentinel inside Terraform Cloud the validation appears in the run output and in the policy results panel. A failing policy produces a “Policy check: Hard mandatory” with a result of false.

Production failure modes

The five failure modes to recognise:

  1. Double-up rule catalogues. A team runs Sentinel and Checkov against the same plan. The Sentinel rule says “S3 must have encryption”; Checkov has the equivalent. The rule fails twice in CI. Engineers fix the warning twice. One catalogue must win for any given check; the other catalogues complement, not duplicate.
  2. Static-only as the gate. The team runs tfsec in CI and treats the result as the policy check. A variable like encrypt = var.encrypt makes the static check ambiguous. The plan-time gate sees the resolved value; static does not. Plan-time is the gate; static is the fast feedback loop.
  3. Migrating tool, stale rules. A shop standardises on tfsec, then Aqua announces Trivy as the destination. The rule set stops receiving updates. Mitigation: treat the migration as a project, not a side-quest; update the rule catalogue as part of the change.
  4. Custom rules in a different language per tool. Sentinel for Terraform, Cedar for IAM, OPA for K8s. Three rule sets; three authors; three review paths. Where possible, consolidate on OPA / Rego.
  5. Pre-commit as the gate. Engineers can run git commit --no-verify. A pre-commit hook that passes is not a control; it is a hint. The actual gate is in the CI pipeline or in Terraform Cloud.

Security and performance

Each tool carries different surface. Sentinel runs inside Terraform Cloud; the rule source comes from a policy set linked to the workspace, with version pinning. OPA / Conftest runs as a CI binary; rule files are version-controlled. tfsec, Checkov, and Trivy each pull rule definitions from their respective distributions on every run; an air-gapped environment should pin the rule set to a specific version and vendor the tarball.

Performance is rarely the limiting factor for any of these tools on a 200-resource plan. The Rego parser is the slowest of the three, but the run time is dominated by terraform plan itself, not by Conftest. The bottleneck shifts to plan generation at a few hundred resources; for larger fleets, plan caching and incremental plans address the plan side, not the policy side.

What comes next

Tools are the substrate. The next lesson is about the rules themselves: how to write them well, the right abstraction level, and the test-driven authoring workflow that keeps a rule set maintainable.

Verification

conftest --version
tfsec --version
checkov --version
trivy --version
conftest version 0.55.0
tfsec version 1.28.7 (built 2024-08-12)
checkov 3.0.50
trivy 0.51.0

A representation across the stack:

conftest test plan.json --policy policy/ && tfsec . && \
  checkov -d . --quiet && trivy config --quiet .
5 tests, 5 passed
OK - 14 files scanned, no issues
Passed: 14, Failed: 0
No trivy-iac security issues found

All four exit with status 0 on a clean project. Any non-zero exit is a policy violation; the CI job is configured to fail on any non-zero exit.

Knowledge check · 7 questions

  1. Q1. Which layer is the only one that can gate the apply?

  2. Q2. A team of 25 engineers runs Terraform via self-hosted CI and does not use Terraform Cloud. Which tool stack is most defensible?

  3. Q3. tfsec is the destination for the static-analysis rule set; it is no longer being developed.

  4. Q4. Which tool is best suited for a regulated workload where auditor checklists must map to rule IDs?

  5. Q5. Which statements are true of Open Policy Agent? (Select all that apply.)

  6. Q6. A custom rule needs to verify that S3 buckets created by Terraform have SSE-KMS encryption with a specific CMK. Which toolset is best?

  7. Q7. A CI pipeline runs tfsec and Checkov, both fail with the same rule (CKV / AVD variant: 'S3 must have encryption'). Engineers fix the warning twice in the same PR. What is the fix?

Passing score: 75%. Answers are checked in this browser.