IaC and the Security Drift Problem: Why Terraform Alone Is Not Enough

Godfrey Maiwun  ·  October 2025  ·  DevSecOps  ·  11 min read

Infrastructure-as-code was supposed to solve the configuration drift problem. Define your infrastructure in code, apply it consistently, version control the state, and your environments stay what you said they were. This works remarkably well for provisioning drift. It works much less well for security drift.

Two different drift problems

Provisioning drift is the gap between your Terraform state and the resources that exist in your cloud account. Someone adds an EC2 instance manually; your state file does not know about it. IaC solves this through its state management model: terraform plan shows the difference, terraform apply reconciles it. The model is sound and well-understood.

Security drift is a different problem. It is the gradual divergence between the security configuration your Terraform describes and the actual security posture of your environment — caused not by resource creation but by configuration changes, permission escalations, manual emergency fixes, and the slow erosion of enforcement that happens in any organisation under operational pressure.

A security group rule broadened to fix a production incident and never narrowed again. An S3 bucket policy amended manually by an engineer who did not want to wait for a Terraform PR to merge. An IAM role with permissions added directly in the console because the deployment was urgent. Each of these changes is invisible to Terraform's state unless someone runs a plan, notices the diff, and chooses to act on it rather than ignore it or accept it.

Why Terraform's drift detection is insufficient

Terraform detects changes to resources it manages when you run a plan. This has three gaps as a security control. First, it only detects drift when someone runs it — in environments with infrequent Terraform runs, drift can accumulate for weeks. Second, it only covers resources that Terraform manages — manually created resources, or resources created by other tools, are invisible. Third, it surfaces drift as an infrastructure change, not as a security finding — a broadened security group rule appears the same as an instance type change, with no automatic severity rating or security context.

There is also the human factor. When terraform plan shows that a production security group has changed, the instinct is often to accept the change and import it into state rather than to investigate whether it represents a security issue. The operational culture around Terraform runs tends to treat unexpected diffs as noise to resolve rather than signals to investigate.

Security drift is not a Terraform problem. It is an enforcement and detection problem that requires tooling specifically designed for security posture management, not infrastructure state management.

Policy-as-Code: the first line of defence

The most effective pattern for preventing security drift is catching misconfigurations before they reach production — in the CI/CD pipeline, before terraform apply runs. This is the Policy-as-Code approach, implemented through tools like Open Policy Agent (OPA) with Rego, Checkov, or Terrascan.

Catching misconfigurations before they reach production.

The pattern: your CI pipeline runs Terraform plan, generates a plan file, and passes it to a policy evaluation tool. The tool checks the planned changes against your organisation's security policies — encryption required on all storage, no security groups with 0.0.0.0/0 on privileged ports, IAM policies must not grant * actions on * resources, all S3 buckets must have Block Public Access enabled. Failed policies fail the pipeline. The Terraform apply never runs.

Checkov is a good starting point — it ships with hundreds of pre-built checks for common cloud misconfigurations and requires minimal configuration. OPA with Rego gives you the flexibility to express complex, organisation-specific policies that off-the-shelf tools cannot cover. The two can coexist: Checkov for common patterns, OPA for bespoke controls.

The key insight is that prevention is cheaper than detection and remediation. A misconfiguration caught in a PR review costs 10 minutes to fix. A misconfiguration caught by an auditor costs weeks.

Continuous posture management: detecting what slips through

Policy-as-Code catches changes made through the pipeline. It does not catch changes made outside it. For that, you need continuous cloud security posture management (CSPM) — tools that continuously scan your cloud environment and compare it against security benchmarks.

Detecting what slips through the pipeline.

AWS Security Hub with the CIS AWS Foundations Benchmark enabled is a reasonable CSPM baseline for AWS environments — free for the standard checks, continuously updated, and integrated with other AWS services. Commercial CSPM tools (Wiz, Orca, Prisma Cloud) offer deeper coverage and multi-cloud support at cost.

The output of CSPM should be a finding queue, not a dashboard that someone reviews quarterly. Findings above a defined severity threshold should be routed to the owning team with a remediation deadline. Critical findings — public S3 buckets, unrestricted security groups, root access keys — should trigger immediate alerts, not appear in a weekly report.

The integration between CSPM findings and your IaC workflow is where the loop closes. When CSPM identifies a manual configuration change that deviates from your declared IaC posture, the remediation path should be a Terraform PR that corrects the configuration and re-establishes the managed state — not a manual fix in the console that creates more drift.

Immutable infrastructure as a drift prevention strategy

The most radical approach to security drift is eliminating the possibility of configuration changes in production: immutable infrastructure, where servers are never modified after deployment but are replaced entirely when changes are needed. If you cannot SSH into a production server and change a security group rule manually because the server does not accept SSH connections and the security group is managed by a pipeline-only IAM role, drift from manual changes becomes structurally impossible.

This is achievable for stateless workloads on modern cloud architectures: containerised applications, Lambda functions, ECS tasks. It is harder for stateful legacy systems, for environments with operational requirements that demand interactive access, and for teams that have not yet built the pipeline maturity to deploy changes confidently through automation.

The intermediate position — not full immutability, but pipeline-only access to production configuration changes — is achievable in most environments with IAM boundary policies that restrict direct console access to production resources. Engineers can read production state; only the pipeline can write it.

The practical starting point

If you are managing infrastructure with Terraform and have not yet addressed security drift: add Checkov to your CI pipeline this week. It requires three lines of pipeline configuration and will immediately surface existing issues in your Terraform code. Set up AWS Security Hub with CIS Benchmarks in your production account. Run a report of findings by severity. Treat the critical findings as a sprint backlog item, not a compliance task.

Terraform is a powerful tool for infrastructure management. It is not a security control. The security posture of your infrastructure requires dedicated enforcement — in the pipeline before deployment, and continuously after it.


Filed under: DevSecOps

More writing Nov. 2025
Cloud-Native Security: What the Shared Responsibility Model Ac…
Cloud Security
Sep. 2025
Zero Trust at Scale: A Reality Check for Practitioners
Security Architecture

All writing →