Terraform / Sensitive data, governance, and recovery / Lesson 16
CI artifacts, policy, and exact-plan approval
Bind automation decisions to reviewed artifacts and trusted execution rather than assuming a pipeline label makes infrastructure changes safe.
On this page
Lesson goals
- Define trustworthy source, dependency, input, plan, and approval identities.
- Inspect synthetic action policy while accounting for replacements and sensitive JSON.
Infrastructure code is executable through several channels
A pipeline can fetch modules and providers, evaluate data sources, access backends, and eventually change external objects. Untrusted source changes therefore require isolation and an appropriate permission model even before application. Separate review-only jobs from privileged execution identities, and protect dependency origins and lock evidence. Short-lived credentials can reduce exposure but still need narrow scope and trusted issuance. A pull request title or a green generic build is not evidence that the intended account, state, configuration, and proposed actions were reviewed.
Machine-readable plans remain sensitive artifacts
The command below would read a saved plan and emit Terraformโs documented JSON representation if executed with a compatible CLI. It is not run. JSON can expose values hidden in ordinary human-readable output, so storage, logs, retention, and policy processors need confidentiality controls. Parse the documented format version and required structures rather than scraping console text or assuming an omitted field means no change. Bind approval to the exact saved artifact and its source/input/dependency context; applying a different newly generated plan invalidates that relationship.
terraform show -json review.tfplan
The command is non-runnable and no plan file is opened. The example describes an artifact boundary, not safe-to-publish output. A real consumer must handle format compatibility, unknown and sensitive values, omitted structures, and resource action ordering according to the official JSON contract.
Replacements contain a destructive action too
The offline record below is an authored subset of plan-shaped data, not a complete Terraform plan schema or a production policy implementation. Its rule rejects any listed delete action, including deletion within a replacement sequence. This is stricter than some legitimate workflows and deliberately chosen for the exercise. A real policy needs resource identity, environment, unknowns, exceptions, data retention, and provider semantics. Counting only entries whose actions equal exactly delete can accidentally miss create/delete or delete/create replacements.
changes = [
{'address': 'terraform_data.catalog', 'actions': ['update']},
{'address': 'terraform_data.release', 'actions': ['create', 'delete']},
]
blocked = sorted(c['address'] for c in changes if 'delete' in c['actions'])
print('blocked=' + ','.join(blocked))
print(f'approved={not blocked}')
blocked=terraform_data.release
approved=False
The synthetic release replacement is blocked because its action list contains delete. The model reads no real plan or state and grants no execution approval. It checks one declared policy condition rather than validating the entire artifact format or operational safety.
Approval and concurrency need the same intended context
A useful approval record identifies the source revision, toolchain, provider and module selections, nonsecret input identity, backend/state, artifact digest, reviewer, and relevant policy decision. Serialize cooperating writers and reject changed context rather than disabling stale-plan or lock checks. Provider permissions should match the approved scope, not a convenient administrator role. Protect credentials and artifacts from untrusted jobs, and keep emergency exceptions explicit, limited, and auditable. Automation can enforce these boundaries, but its existence alone does not prove they were configured correctly.
A policy decision is not a service acceptance test
A plan policy can reject a known forbidden proposal but cannot by itself prove successful application, readiness, remote API behavior, or recovery from partial failure. Record actual execution results and verify intended identities, data, access, and application behavior afterward through the authorized workflow. Keep failures visible and preserve enough redacted evidence for reconciliation. This course runs only the small in-memory policy example; it never triggers CI jobs, accesses a real plan artifact, obtains credentials, or performs Terraform or cloud operations.
Common errors and fixes
Approval applies to a newly regenerated plan with the same filename.
- Why it happens
- Friendly artifact naming replaced exact content and context identity.
- How to fix it
- Require review of the actual artifact and reject changed inputs or state context.
- Prevent it next time
- Bind approvals to immutable evidence rather than mutable labels.
A deletion policy misses replacements.
- Why it happens
- The rule checked only a single-action delete list.
- How to fix it
- Inspect every supported action sequence and its resource semantics.
- Prevent it next time
- Test update, delete, create/delete, and delete/create cases explicitly.
Raw plan JSON is published as harmless build output.
- Why it happens
- Machine-readable data was assumed to inherit console redaction guarantees.
- How to fix it
- Restrict access, redact appropriate reports, and handle exposure through the approved process.
- Prevent it next time
- Treat plan and state artifacts as sensitive by design.
Check your understanding
1. Why does the example block create followed by delete?
Show worked solution
The stated policy forbids any delete action, and replacement includes one even when creation occurs first. Ordering changes availability implications but does not erase deletion. A real organization may authorize some replacements under a richer policy; that exception needs explicit identity, data, and review conditions.
2. Does a passing policy guarantee that application may run under any account?
Show worked solution
No. Execution identity, state target, credentials, and source trust remain separate approval boundaries. A correct decision over one artifact cannot authorize another environment. Preserve context and least privilege, then verify the actual result rather than treating a green policy status as universal permission.
Key takeaways
- Approve exact artifacts under exact state and execution context.
- Policy, concurrency, confidentiality, and outcome verification are separate controls.