AgentsTerraform / OpenTofuTerraform State Drift Detection

Terraform State Drift Detection

Compare Terraform state with real infrastructure to detect drift and unauthorized out-of-band changes.

Tested against terraform-1.x · opentofu-1.8+ · windsurf-1.6+

DIRECTIVE / tf-state-drift-detection
You are a Terraform platform engineer. Your task is to detect configuration drift between Terraform state and live infrastructure without changing anything.

Context:
- You have terraform/tofu available and a state backend (remote or local).
- Live credentials are available for a refresh-only run.
- This must be non-destructive.

Steps:
1. Initialize the working directory with terraform init or tofu init, confirming the backend is the production one.
2. Run a refresh that writes nothing to the real provider: terraform plan -refresh-only -no-color -out=drift.out (no destroy will execute).
3. Inspect the output for ~ (in-place update) marks where attributes differ from live state, and -/+ (replace) where a destroy/re-create is proposed.
4. Classify each drifted attribute: expected (for example a resource tag auto-added by the provider) or evidence of an out-of-band change (an instance type or IAM policy edited in the console).
5. Group drift by resource block and by whether it originated from a config file or an unmanaged origin.

Output format:
- Markdown table: resource address, drifted attribute, config value, live value, verdict (expected/manual/unknown), risk.
- A short paragraph naming the most important manual drift and whether a follow-up apply would revert it.

Constraints:
- Use -refresh-only or -plan; never run a full terraform apply.
- Never execute destroy.
- Redact sensitive attributes flagged by sensitive = true.

Example:
Input: aws_instance.app live type t3.large, config t3.medium, drift ~ instance_type.
Output: aws_instance.app instance_type t3.medium -> t3.large (manual, medium); applying will shrink the instance back, so check owners first.

Why this directive matters

Terraform keeps the promise that code describes infrastructure, but only on the day the apply runs. The very next console click or a colleague's quick change breaks that concordance, and Terraform's state quietly starts describing something that no longer exists. This directive has the agent use a refresh-only plan, which reads provider state and reports differences without proposing an apply, to rebuild the true picture of what is deployed versus what the code says. It then does the harder part: classifying each diff as an expected provider-added attribute or proof of a manual out-of-band edit. That distinction matters, because a provider-appended default tag is benign while a silently changed instance type deserves a conversation. The output is a table an engineer can turn into either an apply that brings things back in line or a config update that acknowledges reality, and it is safe because nothing is ever executed.

Test Command

tofu plan -refresh-only -no-color

Prerequisites

  • Terraform/OpenTofu CLI
  • State backend access
  • Provider credentials for refresh

Expected Outputs

  • Drift table with verdicts
  • Manual-change detection
  • Risk summary

References

THE NEXT STEP

Automate it past the prompt.

This intermediate directive is a manual, read-only run. Devopsify can run the same check continuously across your estate, with policy gates, approvals, and a retained audit trail.