# Terraform Validate

> Validate Terraform modules and configurations across CPP infrastructure repos. Use when checking Terraform code, reviewing infrastructure changes, or verifying module consistency. Use when this capability is needed.

- Skill: `tomevault-io/terraform-validate-2` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add tomevault-io/terraform-validate-2`
- Raw SKILL.md: https://api.skillmd.com/api/skills/tomevault-io/terraform-validate-2/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: DevOps & Infra
- Author: tomevault-io (https://skillmd.com/u/tomevault-io)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/tomevault-io/terraform-validate-2

---


# Terraform Validate

Validates Terraform modules and configurations across CPP infrastructure repositories for consistency, security, and best practices.

## When to Use

- User asks to "validate terraform", "check this module", "review infrastructure changes"
- User is modifying a `cpp-terraform-*` or `cpp-module-terraform-*` repo
- User wants to verify state backend configuration
- User wants to check variable naming conventions across modules

## Process

### Step 1: Identify Module Type

| Prefix | Type | Purpose |
|--------|------|---------|
| `cpp-module-terraform-azurerm-*` | Reusable module | Shared building blocks consumed by other Terraform repos |
| `cpp-terraform-azurerm-*` | Root module | Environment-specific infrastructure provisioning |
| `cpp-terraform-network` | Network | VNet, subnet, NSG, peering configuration |
| `cpp-automation-terraform` | Automation | Terraform automation and orchestration |

### Step 2: Validate Structure

Every Terraform repo should have:

```
├── main.tf                    # Primary resource definitions
├── variables.tf               # Input variable declarations
├── outputs.tf                 # Output value declarations
├── versions.tf                # Provider and Terraform version constraints
├── README.md                  # Auto-generated by terraform-docs
├── .pre-commit-config.yaml    # Pre-commit hooks
├── .terraform-version         # tfversion pinning
└── vars/                      # Environment-specific tfvars (root modules only)
    ├── dev.tfvars
    ├── sit.tfvars
    ├── ste.tfvars
    ├── nft.tfvars
    ├── prp.tfvars
    └── prd.tfvars
```

### Step 3: Validation Checks

#### Variable Declarations
- [ ] All variables have `description` field
- [ ] All variables have `type` constraint
- [ ] Sensitive variables marked with `sensitive = true`
- [ ] Default values only for optional variables
- [ ] Variable names use snake_case

#### Resource Configuration
- [ ] All resources have consistent tagging (environment, team, service)
- [ ] Resource names follow CPP naming convention: `{resource-type}-{env}-{purpose}`
- [ ] No hardcoded values that should be variables
- [ ] Lifecycle rules specified where appropriate (prevent_destroy for stateful resources)

#### State Backend
- [ ] Backend configuration uses Azure Storage Account
- [ ] Non-live state: `samdvshared01` in `RG-MDV-SHARED-01`
- [ ] Live state: `sampdshared01` in `RG-MPD-SHARED-01`
- [ ] State container names are unique per workspace

#### Security
- [ ] No secrets in `.tf` files or `.tfvars` (use Key Vault references)
- [ ] NSG rules follow least-privilege principle
- [ ] Private endpoints used for Azure PaaS services
- [ ] Managed identities preferred over service principals
- [ ] No `*` in RBAC role assignments

#### Pre-commit Hooks
- [ ] `.pre-commit-config.yaml` present
- [ ] Hooks include: terraform-fmt, terraform-validate, terraform-docs, tflint
- [ ] Hook versions are current

### Step 4: Environment Consistency

For root modules with per-environment tfvars:

1. Read all `vars/*.tfvars` files
2. Verify each environment defines the same set of variables
3. Flag any environment-specific variables missing from other environments
4. Check that production values are appropriately different from non-prod (e.g., larger SKUs, more replicas)

### Step 5: Module Dependency Check

For root modules that consume reusable modules:

1. Check `module` blocks for source references
2. Verify module versions are pinned (not `ref=main`)
3. Check if newer versions of consumed modules are available
4. Verify required input variables are provided

### Step 6: Generate Report

```
## Terraform Validation Report: [module-name]

### Structure
- [✅/❌] Standard file layout
- [✅/❌] Pre-commit hooks configured
- [✅/❌] README auto-generated

### Variables
| Name | Type | Description | Sensitive | Default | Status |
|------|------|-------------|-----------|---------|--------|

### Security
- [✅/❌] No hardcoded secrets
- [✅/❌] Private endpoints used
- [✅/❌] Managed identities preferred

### Environment Consistency
| Variable | dev | sit | ste | nft | prp | prd |
|----------|-----|-----|-----|-----|-----|-----|

### Issues
- [severity] [description] — suggested fix
```

## CPP-Specific Infrastructure Patterns

### AKS Clusters
- System + Worker + Prometheus node pools
- Azure CNI networking with Calico network policy
- OIDC issuer enabled for workload identity
- Cluster naming: `{env}-cs{stack}cl{cluster}`

### PostgreSQL
- Flexible Server (not single server)
- Per-context databases (hearing_db, resulting_db, etc.)
- Admin credentials from Key Vault
- Read-only user for reporting (`pgreadonly`)

### Service Bus
- Per-environment namespace
- Topics per bounded context
- Dead-letter queues configured
- Max delivery count and TTL set per subscription

### Key Vault
- Per-environment vaults
- CSI driver for pod secret injection
- Secret rotation enabled

---
> Source: [hmcts/cpp-context-staging-bulkscan](https://github.com/hmcts/cpp-context-staging-bulkscan) — distributed by [TomeVault](https://tomevault.io).
<!-- tomevault:4.0:skill_md:2026-05-22 -->

