# Infrastructure as Code Maturity and Test Strategy

> **Intro:** IaC programs usually fail in one of two ways: they stay manual and ad hoc, or they become “fully automated” without trustworthy validation. This page focuses on the middle ground that actually works: grow IaC maturity together with testing maturity.
>
> **What this page includes**
>
> * a practical maturity model for Terraform- or IaC-centered teams
> * a test stack from format and validation through plan and environment tests
> * examples for modern and legacy tooling
> * rollout advice for platform, cloud, and Product Security teams

## Why maturity matters

A lot of teams say “we use Infrastructure as Code” when they really mean one of these:

* someone wrote Terraform once but production changes still happen manually;
* a few modules exist, but nobody trusts the plans;
* the code is versioned, but review, policy, testing, and evidence are weak;
* the deployment is automated, but drift, exceptions, and documentation are unmanaged.

## A practical IaC maturity model

| Level | Name                   | Typical traits                                                      | Main security risk                                            |
| ----- | ---------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------- |
| 0     | Manual or script-heavy | console changes, copy-paste, poor reviewability                     | no trustworthy source of truth                                |
| 1     | Basic IaC adoption     | Terraform or similar exists, but structure is inconsistent          | drift and unsafe patterns spread quickly                      |
| 2     | Reviewable IaC         | modules, pull requests, plan review, linting                        | security still depends on human reviewers catching everything |
| 3     | Tested IaC             | validation, policy checks, plan analysis, environment tests         | false confidence if tests only check syntax                   |
| 4     | Governed IaC           | policy exceptions, evidence, reusable safe modules, release control | operational overhead if the policy model is too brittle       |
| 5     | Adaptive IaC           | drift feedback, evidence reuse, metrics, module-first prevention    | complexity can outgrow team capacity if ownership is unclear  |

## The test stack that works in practice

### Layer 1 — formatting and syntax

```bash
terraform fmt -check -recursive
terraform init -backend=false
terraform validate
```

### Layer 2 — static misconfiguration and policy checks

```bash
checkov -d .
trivy config .
docker run --rm -v "$PWD:/path" checkmarx/kics scan -p /path
conftest test --policy policies terraform/
```

### Layer 3 — plan-aware policy checks

```bash
terraform plan -out=tfplan
terraform show -json tfplan > tfplan.json
jq '.resource_changes[] | {address, actions: .change.actions}' tfplan.json
```

### Layer 4 — environment or contract tests

Modern pattern:

* **terraform test**
* **Terratest** when code-driven integration tests are worth the extra overhead

Legacy or older pattern:

* **Kitchen-Terraform**

### Layer 5 — post-deploy drift and posture review

Purpose:

* confirm runtime stayed aligned with approved intent;
* detect console changes, weak defaults, or cloud-side deviations.

## Practical CI pattern

### Fast path for pull requests

Run:

* `terraform fmt -check`
* `terraform init -backend=false`
* `terraform validate`
* `checkov -d .`
* `trivy config .`

### Medium path for protected branches

Run:

* all fast checks
* `terraform plan`
* plan JSON extraction
* custom policy checks on the plan
* docs generation if modules changed

### Deep path for risky modules

Run:

* all medium checks
* `terraform test`
* selective environment tests
* cloud-side smoke tests in isolated accounts

## Modern vs legacy tooling notes

### tfsec

You will still see older pipelines using:

```bash
tfsec .
```

This is useful as historical context, but many teams now standardize on:

```bash
trivy config .
```

### Kitchen-Terraform

This was a common environment testing pattern in older Terraform programs. It is still educational, but newer teams often prefer:

* `terraform test` for native module testing
* Terratest for richer integration logic
* policy plus plan checks for most everyday gates

## Example: pre-commit style local checks

```bash
#!/usr/bin/env bash
set -euo pipefail

terraform fmt -check -recursive
terraform init -backend=false >/dev/null
terraform validate
checkov -d .
trivy config .
```

See [`../snippets/terraform/iac-local-checks.sh`](https://github.com/D3One/Product-Security-Gitbook/blob/main/snippets/terraform/iac-local-checks.sh).

## Example: native Terraform tests

```bash
terraform test
```

Use native tests for:

* module input validation expectations;
* output expectations;
* assumptions about resource composition;
* reusable module safety checks.

## What Product Security should push for first

If your organization is early:

1. stop manual console changes from being the “real” deployment path;
2. require PR review and plan visibility;
3. add one static scanner and one policy layer;
4. separate warning-only checks from true blockers;
5. treat shared modules as higher-trust assets with stronger tests.

## Related pages

* [🛡️ Security as Policy for Terraform and Infrastructure as Code](/cloud-kubernetes-and-infrastructure-security/index/security-as-policy-for-iac.md)
* [🧱 Terraform Security Scanning and Checkov](/cloud-kubernetes-and-infrastructure-security/index/terraform-security-scanning-and-checkov.md)
* [🧱 Terraform Top 10 Misconfigurations](/cloud-kubernetes-and-infrastructure-security/index/terraform-top-10-misconfigurations.md)
* [🛰️ Cloud Auditing by API and Configuration State](/cloud-kubernetes-and-infrastructure-security/index/cloud-auditing-by-api-and-configuration-state.md)

\---*Author attribution: Ivan Piskunov, 2026 - Educational and defensive-engineering use.*


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.product-security.expert/cloud-kubernetes-and-infrastructure-security/index/infrastructure-as-code-maturity-and-test-strategy.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
