Skip to content

Latest commit

 

History

5 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

plan-skeptic

Flag the parts of a Terraform/OpenTofu plan that need a human.

AI assistants write infrastructure changes that are fluent, plausible and occasionally destructive: a rename that replaces a database, a policy widened to s3:* to make an error go away, SSH opened "temporarily". The diff reads fine. The plan says what will actually happen. plan-skeptic reads the plan and points at the lines a reviewer must not skim.

It is not a policy engine and does not try to replace one. It is eleven opinionated checks about what a change introduces, tuned so that the output is short enough to be read on every pull request.

$ terraform plan -out=plan.out && terraform show -json plan.out > plan.json
$ plan-skeptic plan.json
plan-skeptic: 2 finding(s) across 1 resource change(s)

[HIGH  ] PS001 stateful-resource-replaced
         aws_db_instance.orders: aws_db_instance will be replaced because identifier changed: destroyed, then recreated empty.
         why a human should look: Replacement is destroy-then-create unless create_before_destroy is set. ...

[MEDIUM] PS010 recovery-guard-removed
         aws_db_instance.orders: deletion_protection changes true -> false.

Works the same with tofu show -json. No dependencies; Python 3.9+.

Install

pipx install git+https://github.com/TellersTechOrg/plan-skeptic
# or run from a checkout
PYTHONPATH=src python3 -m plan_skeptic plan.json

GitHub Action

- run: |
    terraform plan -out=plan.out
    terraform show -json plan.out > plan.json
- uses: TellersTechOrg/plan-skeptic@v0.1.1
  with:
    plan-json: plan.json
    fail-on: high          # high | medium | low | never
- uses: github/codeql-action/upload-sarif@v3
  if: always()
  with:
    sarif_file: plan-skeptic.sarif

Findings appear in the job summary, the Security tab (when SARIF is uploaded), and inline on the pull request. Uploading SARIF needs security-events: write.

Rules

Id Severity Flags
PS001 high A data-holding resource (database, bucket, table, volume, key, PVC) is destroyed or replaced, and why it is being replaced
PS002 medium Any other resource is deleted
PS003 high An IAM policy (including role inline_policy) newly grants * / service:*, or uses NotAction in an Allow
PS004 high AdministratorAccess, PowerUserAccess or IAMFullAccess is attached
PS005 high A trust policy lets any principal assume the role without a Condition
PS006 high Ingress opened to 0.0.0.0/0 or ::/0 (medium for ports 80 and 443)
PS007 high An S3 bucket made public by ACL, bucket policy or public access block
PS008 high A database given publicly_accessible = true
PS009 medium Encryption at rest set to false
PS010 medium deletion_protection switched off, or skip_final_snapshot / force_destroy switched on
PS011 high A KMS key policy lets any principal use the key without a Condition

A delete paired with a create of the same type and name gets a hint to use a moved block, since that is what an unfinished refactor looks like.

What it deliberately does not do

  • It reports changes, not state. An update that leaves an existing 0.0.0.0/0 rule alone is not flagged. Scanning everything on every plan is how a tool's output stops being read.
  • Unknown-after-apply values never trigger a rule. Guessing at a value the plan itself cannot see would invent findings.
  • AWS first. Replacement detection covers AWS, GCP, Azure and Kubernetes storage; the exposure and IAM rules are AWS-only in v0.1.

Options

plan-skeptic PLAN [--format text|json|sarif] [--output FILE]
                  [--fail-on high|medium|low|never] [--disable RULE ...]
                  [--list-rules]

Exit codes: 0 nothing at or above --fail-on, 1 findings at or above it, 2 the input could not be reviewed. A binary plan file or a state file is refused with exit 2 rather than reported clean.

Fixtures

fixtures/ holds eight flawed plans, each paired with the request that produced it, plus a clean control. They are the exercises for the Confidently Wrong workshop and come from the same material as the book Confidently Wrong.

Development

python3 -m unittest discover -s tests

License

MIT

About

Flag the parts of a Terraform/OpenTofu plan that need a human. Ten checks, SARIF output, GitHub Action.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages