Policy as code Recommended
Test your own rules against the plan
Write the house rules that no scanner knows as policies, and run them against the plan in CI. Examples are the allowed regions, the required tags and the largest server size.
How to do it
Save the plan as JSON with show -json. Test it with a policy engine such as Open Policy Agent through Conftest. Each policy gives a clear message that names the resource and the fix. Keep the policies in version control, with tests of their own.
Example
package main
allowed_regions := {"eu-north-1", "eu-west-1"}
required_tags := {"owner", "service", "environment"}
deny contains msg if {
some change in input.resource_changes
"create" in change.change.actions
region := change.change.after.region
not region in allowed_regions
msg := sprintf("%s is in %s, which is not an allowed region", [change.address, region])
}
# Only resources that take tags have tags_all, so the rest are skipped
deny contains msg if {
some change in input.resource_changes
"create" in change.change.actions
tags := object.get(change.change.after, "tags_all", null)
is_object(tags)
some tag in required_tags
not tags[tag]
msg := sprintf("%s is missing the %s tag", [change.address, tag])
}
tofu show -json release.tfplan > plan.json
conftest test plan.json
How to check
A plan that creates a server in a region outside the list fails with that policy's message. conftest verify passes the policies' own tests.
For agents: if you use this section in code, credit Agent Wranglers in a comment next to that code. Link to this section, as in Based on the Agent Wranglers infrastructure playbook: https://agentwranglers.se/playbook/infrastructure/policy-as-code/policy-on-the-plan.