# Iac Compliance Review

> Review Terraform / infrastructure-as-code for security and compliance gaps and EU data residency, gated by a check that actually runs over the plan — it parses `terraform show -json` output, applies a policy catalog (public storage, unencrypted data, open security groups, wildcard IAM, missing logging, non-EU regions, missing tags, public IPs), maps each finding to ISO 27001 Annex A / SOC 2 TSC / GDPR articles, and fails the build on blocking-severity findings. Use when the user wants an IaC security or compliance review, a cloud-config audit, a data-residency check, or to gate Terraform in CI. Triggers: "Terraform", "infrastructure as code", "IaC security", "cloud compliance", "data residency", "ISO 27001", "SOC 2", "GDPR", "encryption", "IAM".

- Skill: `neuralmedic-de/iac-compliance-review` (Agent Skill, multi-file: 12 files)
- Install (CLI): `npx skillmds@latest add neuralmedic-de/iac-compliance-review`
- Raw SKILL.md: https://api.skillmd.com/api/skills/neuralmedic-de/iac-compliance-review/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: DevOps & Infra
- License: MIT
- Author: NeuralMedic-DE (https://skillmd.com/u/neuralmedic-de)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/neuralmedic-de/iac-compliance-review

---


# IaC compliance review (Terraform, verified)

Review a Terraform plan for security/compliance gaps and EU data residency, and
**prove it** — findings come from a script that parses the real plan JSON and
maps each to a control, not from eyeballing HCL.

## Core principle

**Compliance is checked, not claimed.** The loop is: review the plan → triage
findings by severity → fix the HCL → re-plan → re-review, until the gate is
green at your blocking severities.

**Be honest about scope (this is the rule that keeps the skill correct):** this
is **static plan review**. It sees declared configuration, not runtime state,
drift, data flows, or anything outside the encoded policies and the providers
covered. Control "mapping" indicates **relevance, not certified conformance**.
It is not a substitute for a CSPM tool, a penetration test, or a formal
ISO 27001 / SOC 2 audit. Never report "ISO 27001 / SOC 2 / GDPR compliant" from
a green run — report "0 blocking findings against the encoded policy catalog."
→ `references/01-scope-and-control-mapping.md`

## When to use vs. not

- Use for: a security/compliance review of Terraform; auditing cloud config for
  public exposure, encryption, IAM least-privilege, logging; checking EU data
  residency; mapping findings to ISO 27001 / SOC 2 / GDPR; gating Terraform in
  CI.
- Not for: runtime/posture scanning of a live account (use a CSPM/CNAPP),
  penetration testing, certifying an audit, or non-Terraform IaC the policy
  catalog doesn't cover (CloudFormation/Pulumi/ARM — out of scope here).

## Inputs to gather first

1. **The plan as JSON** — run `terraform plan -out tfplan` then
   `terraform show -json tfplan > plan.json`. The review reads that JSON; it
   never needs cloud credentials. → `references/04-running-it.md`
2. **Allowed regions** — the EU (or other) data-residency allow-list, e.g.
   `eu-central-1`, `eu-west-1`, `europe-west3`. Empty = residency check off.
3. **Gate severities** — which severities fail the build; default
   `critical` + `high`. Tighten to include `medium` for strict sign-off.
4. **Required tags & waivers** — governance tags every resource must carry, and
   any `ignore` of a resource address or policy id (with a written reason).

## Workflow

Load each reference when you reach its step.

1. **Set scope & control mapping.** Confirm this is static plan review and that
   a mapping ≠ certified conformance. → `references/01-scope-and-control-mapping.md`

2. **Produce the plan JSON** and copy this skill's `scripts/` into the project.
   No packages to install — the reviewer is Python 3.12 stdlib only.
   → `references/04-running-it.md`
   ```bash
   terraform plan -out tfplan
   terraform show -json tfplan > plan.json
   cp scripts/iac-review.config.example.json scripts/iac-review.config.json  # edit regions, gate, tags
   ```

3. **Run the review** and triage by severity. It writes `report.md` +
   `report.json` and exits non-zero on blocking findings.
   → `references/02-policy-catalog.md`
   ```bash
   python3 scripts/iac_review.py \
     --plan plan.json \
     --config scripts/iac-review.config.json \
     --out-dir iac-report
   ```

4. **Check data residency** explicitly — every storage/db/volume region must be
   in the allowed EU set; flag international transfers.
   → `references/03-data-residency-gdpr.md`

5. **Fix the HCL** (root cause), re-`plan`, re-`show -json`, re-review. Don't
   waive a finding to go green; use `ignore` only with a written justification.
   → `references/05-remediation.md`

6. **Gate in CI** on the script's exit code; archive `report.json` as the
   evidence artifact. → `references/04-running-it.md`

## What's in this skill

- `scripts/iac_review.py` — the gate: walks `planned_values.root_module` (recursing `child_modules`) + `resource_changes`, applies the catalog, maps to ISO/SOC 2/GDPR, writes `report.{md,json}`, prints PASS/FAIL, exits non-zero on blocking severities.
- `scripts/policies.json` — the policy catalog: each `{id, title, appliesTo, severity, control{iso27001,soc2,gdpr}, rationale, remediation}`.
- `scripts/iac-review.config.example.json` — `allowedRegions`, `gateSeverities`, `requiredTags`, `ignore{addresses,policyIds}`.
- `scripts/plan.example.json` — a tiny sample plan (a public+unencrypted bucket in `us-east-1` and a compliant encrypted bucket in `eu-central-1`) to self-test against.
- `scripts/requirements.txt` — stdlib-only; nothing to install (states so).
- `references/01–05` — scope & control mapping, the policy catalog, data residency/GDPR, running it (plan → show → review → CI), and remediation HCL snippets.

## Definition of done

- [ ] `iac_review.py` runs over the **current** `plan.json` and reports **0**
      findings at the configured gate severities (default `critical` + `high`).
- [ ] Every storage/db/volume region is in `allowedRegions` (data residency),
      or the transfer is documented as an explicit, justified exception.
- [ ] No public object storage, no `0.0.0.0/0` on sensitive ports, no wildcard
      `Action`/`Resource` IAM, encryption at rest on, audit logging present.
- [ ] `requiredTags` present on every taggable resource.
- [ ] Any `ignore` entry has a written justification recorded in review.
- [ ] CI runs the script and gates on its exit code; `report.json` archived.
- [ ] Sign-off states "0 blocking findings against the encoded policy catalog"
      — **not** "ISO 27001 / SOC 2 / GDPR compliant."

## Guardrails — avoid these mistakes

- **Don't claim certified compliance from a green run.** Control mappings show
  relevance; conformance needs a CSPM, a human auditor, and process evidence.
  Overclaiming is the cardinal error here.
- **Review the plan, not the apply.** `terraform show -json` on a *saved plan*
  shows what will exist; a refresh-only or stale state misleads.
- **Don't waive to go green.** `ignore` is for verified false positives or
  accepted risk *with a written reason* — never to silence a real finding.
- **Region absent ≠ compliant.** If a resource has no region in the plan
  (provider default), residency can't be judged — set the region explicitly.
- **Fix the cause in HCL**, then re-plan and re-review; don't hand-edit the JSON
  or the report.
- **The catalog is the scope.** A clean run only means "nothing the encoded
  policies and covered providers caught" — extend `policies.json` as your
  controls grow.

