Terraform Cloud/Enterprise Sentinel is not the only answer for Terraform policy review. Pre-apply review with OPA (Rego) delivers consistent governance across multiple tools and clouds.
This guide centers on OPA/Rego validation that takes the plan JSON produced by terraform show -json as input, and covers comparisons, implementation patterns, exception management, and the points exams tend to focus on.
Terraform's plan output can be obtained as machine-readable JSON via terraform show -json. OPA (Rego) can take that JSON as input and produce allow/deny decisions, which makes it a great fit for CI gating. It is a strong choice when you are not using Terraform Cloud/Enterprise, or when you want a single policy language across multiple clouds.
In practice you generate the plan in CI, validate the JSON with conftest (a CLI that wraps OPA), and stop the merge or deploy on failure. Because the check runs consistently before apply, governance becomes preventive rather than after-the-fact.
Policy review does not collapse to a single right answer. The best choice depends on team size, platforms in use, existing CI/CD, and operational cost. Below is a summary of the main options and where each fits.
Sentinel on Terraform Cloud/Enterprise is the quickest and most powerful path, but it ties you to the platform. OPA/Rego with Conftest avoids vendor lock-in and adapts to a wide range of use cases. Static HCL analysis (tfsec, Trivy, etc.) catches issues early but does not understand the actual plan diff.
| Approach | Target Layer/Object | Enforcement Point | Strengths |
|---|---|---|---|
| OPA/Rego + Conftest | Terraform plan (JSON) | Right after plan in CI | Low vendor lock-in, expressive, reusable across tools |
| Terraform Cloud/Enterprise Sentinel | Plan/apply between runs | Just before or after plan/apply | Tight platform integration; simple to operate |
| Static HCL analysis (tfsec, Trivy, etc.) | HCL / static code | From PR creation to pre-plan | Early detection; easy to adopt |
| Manual review (review conventions) | PRs / design documents | Anywhere | Flexible; supports context-aware judgement |
At a minimum, reference the resource_changes array and each element's change.after. The targets are typically create, update, and replace (= ["create","delete"]). Exclude pure deletes and no-ops.
Guardrails such as required tags, naming conventions, region restrictions, and size limits become much easier to test when implemented as a pattern that returns a single deny set.
Rego example: require an owner tag policy (input is plan JSON)
package tfplan.tags
deny[msg] {
some i
rc := input.resource_changes[i]
should_check(rc.change.actions)
after := rc.change.after
after != null
required := "owner"
not has_required_tag(after, required)
msg := sprintf("%s.%s is missing tag %q", [rc.type, rc.name, required])
}
should_check(actions) {
actions == ["create"]
} or {
actions == ["update"]
} or {
actions == ["create", "delete"] # replace
}
has_required_tag(after, key) {
tags := get_tags(after)
tags[key]
}
get_tags(obj) = tags {
tags := obj.tags
} else = tags {
tags := obj.tags_all
} else = tags {
tags := {}
}
If the policy's primary goal is to verify the safety of what is about to be created or changed, plan JSON is the first choice. You evaluate the diff directly and keep false positives low. If the goal is inventory work like compliance audits or reconciling an asset register, state JSON is the useful one.
On the Rego side, abstract attribute lookups into helper functions to handle input variation (provider-specific attribute names). Push common concepts like tags and names into wrapper functions so the rule body can focus on business intent.
The basic shape has three steps: 1) terraform init/plan, 2) convert to JSON with terraform show -json, 3) apply Rego with conftest test. Conftest exits 0 on pass and non-zero on deny, so its exit code can serve directly as a job gate.
For multi-module setups, the realistic design is to run plan → conftest in parallel for each directory and fail the whole job if any directory fails. Use caching appropriately to keep plan generation cost down.
Zero exceptions is unrealistic in real environments. Build an exception mechanism into Rego (annotation files or metadata) and explicitly manage the expiration, scope, and rationale. Exceptions must always have an expiration, a reason, and a limited scope.
Policy changes can be breaking. Roll out new rules in stages — warn mode first, then enforce mode — and run them in a CI sandbox period of roughly two weeks to stay safe.
Pro
問題 1
An organization wants to automatically validate required tags and naming conventions against Terraform plans. Terraform Cloud/Enterprise is not in use. Which approach implements a pre-apply gate with the lowest operational cost?
正解: A
An automated pre-apply gate requires evaluating the plan diff. Converting the plan to JSON and validating with OPA/Rego lets you make strict decisions based on the diff and gate CI through the exit code. terraform validate is limited to syntax and some local checks, and manual review or post-hoc audits do not satisfy the automated gate requirement.
Should I feed plan JSON or state JSON into my policy?
Plan JSON is the first choice for pre-apply gates because it evaluates the diff (what is about to change). State JSON is better suited to inventory, post-hoc audits, and asset visibility. A two-tier setup that uses both is also effective.
Provider attribute names differ in Rego. How should I structure this?
Abstract attribute lookups into helper functions so they are decoupled from the rule body. For example, define get_tags that handles both tags and tags_all, and have downstream logic depend on the return value of get_tags.
What should I implement first to start small?
Start with a single high-impact rule in Rego (e.g., require an owner tag on critical resources) and wire the minimal CI path: plan → show -json → conftest. Set up observability for pass/fail (clear deny messages, artifacts) first so the system is easy to extend.
Practice with certification-focused question sets
無料で問題を解いてみるNicheeLab Editorial Team
NicheeLab editorial team focused on data engineering and cloud certification learning. Content is structured around practical study needs and official exam domains.
HCL Syntax: Terraform's Configuration Language (2026)
HCL2 fundamentals for Terraform — blocks, attributes, expres...
Terraform Authoring & Operations Pro: Complete Guide (2026)
Tactics for the Terraform Pro exam — module authoring, works...
Terraform Providers: Plugin Management Fundamentals (2026)
Provider mechanics — required_providers, versions, mirrors, ...
Terraform Resource Blocks: Declarative Infra Units (2026)
Resource block fundamentals — addresses, references, common ...
Terraform Data Sources: Read-Only External Data (2026)
Data source basics — declaration, refresh behavior, dependen...