Skip to content

Terraform Plan Mode

Terraform plan mode produces the highest-fidelity graph because Terraform has already resolved references, modules, provider defaults, and computed resource relationships.

Terraform still runs in the customer's environment. SecureObs does not receive cloud credentials, backend credentials, the binary plan, or the raw JSON plan.

flowchart TD
  Init["terraform init"] --> Validate["terraform validate"]
  Validate --> Plan["terraform plan -out=tfplan"]
  Plan --> Json["terraform show -json"]
  Json --> Scanner["secureobs/scanner plan analysis"]
  Scanner --> Upload["Upload sanitized graph"]
  Scanner --> Cleanup["Delete local plan files"]
Plan and analyze locally
set -euo pipefail
umask 077
export TF_IN_AUTOMATION=1
export TF_INPUT=0

mkdir -p ".secureobs/${CI_RUN_ID}"
terraform init -input=false -lockfile=readonly
terraform validate -no-color
terraform plan \
  -input=false \
  -lock-timeout=5m \
  -out=".secureobs/${CI_RUN_ID}/tfplan"
terraform show -json ".secureobs/${CI_RUN_ID}/tfplan" \
  > ".secureobs/${CI_RUN_ID}/tfplan.json"
chmod 600 ".secureobs/${CI_RUN_ID}/tfplan" \
  ".secureobs/${CI_RUN_ID}/tfplan.json"

Then run the scanner against the JSON path relative to /workspace.

Cleanup

Use the CI platform's unconditional cleanup mechanism:

Cleanup
rm -f ".secureobs/${CI_RUN_ID}/tfplan.json"
rm -f ".secureobs/${CI_RUN_ID}/tfplan"
rmdir ".secureobs/${CI_RUN_ID}" 2>/dev/null || true

Never upload the binary plan or raw plan JSON as a CI artifact.

Requirements

  • Use a pinned Terraform CLI version.
  • Commit .terraform.lock.hcl.
  • Run terraform init -lockfile=readonly.
  • Keep cloud and backend credentials in the CI platform.
  • Prefer same-job analysis so raw plan JSON does not move through artifact storage.

When To Use Existing Plan JSON

If your pipeline already creates a Terraform plan, keep that step and run SecureObs immediately afterward in the same job. Pass the workspace-relative plan JSON path to the scanner.