"In 2019, Capital One lost 100 million customer records because of a misconfigured WAF and overly permissive IAM role. The terrifying part? That configuration likely existed in a template file someone reviewed, approved, and deployed. Infrastructure as Code promised repeatability and auditability—but without security guardrails, it just means you can deploy vulnerabilities faster and more consistently than ever before.".
The Problem: Speed Without Guardrails
IaC tools like Terraform, CloudFormation, and Pulumi have become the backbone of modern cloud operations. Teams provision entire environments in minutes. But speed creates risk. When a developer writes a Terraform module with an S3 bucket policy allowing public read access, that misconfiguration doesn't just exist in one environment—it propagates everywhere the module is used.
The numbers are stark. According to Bridgecrew's 2023 State of IaC Security report, 43% of scanned CloudFormation templates contained at least one misconfiguration. The most common offenders? Overly permissive IAM policies, unencrypted storage, and publicly exposed resources.
The fundamental shift required is simple: treat IaC templates as security artifacts, not just operational ones.
Shift Left: Scanning Templates Before Deployment
The most impactful thing you can do is catch misconfigurations in the CI/CD pipeline—before terraform apply ever runs. Tools like Checkov, tfsec, and KICS analyze your templates statically and flag violations against security benchmarks (CIS, SOC 2, PCI-DSS).
Here's a real-world example. Consider this Terraform snippet:
resource "aws_s3_bucket" "data_lake" {
bucket = "company-data-lake"
}
resource "aws_s3_bucket_acl" "data_lake_acl" {
bucket = aws_s3_bucket.data_lake.id
acl = "public-read"
}Running checkov -d . against this directory immediately flags:
FAILED: CKV_AWS_20 - "Ensure the S3 bucket does not have a public-read ACL"
FAILED: CKV_AWS_145 - "Ensure S3 bucket is encrypted with KMS"
FAILED: CKV2_AWS_6 - "Ensure S3 bucket has a Public Access Block"Three critical issues caught in seconds, before a single API call hits AWS.
Embed Scanning in CI/CD
Detection only matters if it blocks bad deployments. Integrate scanning as a pipeline gate. Here's a GitHub Actions example:
- name: Run Checkov
uses: bridgecrewio/checkov-action@v12
with:
directory: ./terraform
framework: terraform
soft_fail: false # Fail the pipeline on violations
check: CKV_AWS_20,CKV_AWS_145,CKV_AWS_18Setting soft_fail: false means the pull request cannot merge until violations are resolved. This is non-negotiable for production-bound infrastructure.
Write Policies as Code with OPA
Static scanners catch known patterns, but every organization has custom security requirements. Open Policy Agent (OPA) lets you write custom policies in Rego that evaluate Terraform plans:
deny[msg] {
resource := input.resource_changes[_]
resource.type == "aws_iam_policy"
contains(resource.change.after.policy, "\"Action\": \"*\"")
msg := sprintf("Wildcard IAM actions not permitted: %s", [resource.address])
}This catches the all-too-common "Action": "*" in IAM policies that static tools might miss in complex, dynamically composed policy documents.
Beyond Templates: Drift Detection
Securing IaC at deploy time is half the battle. Production configurations drift from their declared state—manual console changes, emergency hotfixes, automated remediation tools. Use terraform plan in detection mode on a schedule, or tools like Driftctl and AWS Config, to continuously compare actual state against your source of truth.
When drift is detected, the response should be automated: alert, log, and optionally remediate by reapplying the declared state.
Building a Mature IaC Security Program
Start with these concrete steps:
- Inventory your IaC — know every template, module, and pipeline deploying infrastructure.
- Scan everything, block on critical — use Checkov or tfsec with pipeline enforcement.
- Write custom policies — encode your organization's specific requirements in OPA.
- Monitor for drift — scheduled plan comparisons with automated alerting.
- Track metrics — measure misconfigurations caught pre-deploy vs. post-deploy. The ratio tells you how mature your program is.
Infrastructure as Code gave us reproducibility. IaC security gives us reproducible confidence. The templates are already there—now make them your strongest security control, not your weakest link.
Have questions about infrastructure as code security? I'm always happy to talk shop — reach out or connect with me on LinkedIn.