Intermediate

Infrastructure as Code Safety

Infrastructure as Code tools provide built-in safety mechanisms that can prevent AI agents from accidentally destroying resources. This lesson covers how to configure these protections across Terraform, Pulumi, and CloudFormation.

Terraform: prevent_destroy Lifecycle Rules

Terraform's prevent_destroy lifecycle meta-argument is your strongest defense against accidental resource deletion. When set, Terraform will refuse to destroy the resource even if terraform destroy is run:

Terraform - Protecting critical resources with prevent_destroy
# Production database - NEVER allow destruction via Terraform
resource "aws_rds_instance" "production" {
  identifier     = "prod-database"
  engine         = "postgres"
  engine_version = "15.4"
  instance_class = "db.r6g.xlarge"

  lifecycle {
    prevent_destroy = true
  }
}

# Production S3 bucket - prevent accidental deletion
resource "aws_s3_bucket" "production_data" {
  bucket = "company-production-data"

  lifecycle {
    prevent_destroy = true
  }
}

# Production VPC - destroying this cascades to everything
resource "aws_vpc" "production" {
  cidr_block = "10.0.0.0/16"

  lifecycle {
    prevent_destroy = true
  }
}
Limitation: An AI agent could remove the prevent_destroy line from your Terraform code before running terraform destroy. To guard against this, use code review requirements (PR approvals) and pre-commit hooks that check for removal of lifecycle protection rules.

Pulumi: protect Property

Pulumi offers the protect resource option, which prevents deletion of a resource even during a pulumi destroy:

Pulumi (TypeScript) - Protecting resources
import * as aws from "@pulumi/aws";
import * as pulumi from "@pulumi/pulumi";

// Production database with deletion protection
const prodDb = new aws.rds.Instance("prod-database", {
  identifier: "prod-database",
  engine: "postgres",
  engineVersion: "15.4",
  instanceClass: "db.r6g.xlarge",
  deletionProtection: true,  // AWS-level protection
}, {
  protect: true,  // Pulumi-level protection (refuses to delete)
});

// Production bucket - double protection
const prodBucket = new aws.s3.Bucket("prod-data", {
  bucket: "company-production-data",
}, {
  protect: true,
  retainOnDelete: true,  // Even if unprotected, keep the resource
});

CloudFormation Stack Policies and Termination Protection

AWS CloudFormation provides two layers of protection: stack-level termination protection and resource-level stack policies:

AWS CLI - Enable stack termination protection
# Prevent the entire stack from being deleted
aws cloudformation update-termination-protection \
  --enable-termination-protection \
  --stack-name production-infrastructure
CloudFormation Stack Policy - Protect specific resources
{
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "Update:*",
      "Principal": "*",
      "Resource": "*"
    },
    {
      "Effect": "Deny",
      "Action": [
        "Update:Replace",
        "Update:Delete"
      ],
      "Principal": "*",
      "Resource": "LogicalResourceId/ProductionDatabase"
    },
    {
      "Effect": "Deny",
      "Action": [
        "Update:Replace",
        "Update:Delete"
      ],
      "Principal": "*",
      "Resource": "LogicalResourceId/ProductionVPC"
    }
  ]
}

State File Protection and Backup

The Terraform state file is one of the most critical files in your infrastructure. If an AI agent corrupts or deletes it, you lose track of all managed resources:

  1. Use Remote State with Locking

    Store state in S3+DynamoDB (AWS), Azure Blob Storage, or GCS with state locking enabled. This prevents concurrent modifications and provides versioning.

  2. Enable State File Versioning

    Turn on S3 bucket versioning for your state bucket. If state gets corrupted, you can roll back to a previous version.

  3. Restrict State Access

    AI agent credentials should have read-only access to state. Only CI/CD pipelines with approved deployments should have write access.

  4. Back Up State Before Changes

    Configure your CI/CD pipeline to snapshot the state file before every terraform apply.

Terraform - Secure remote state configuration
terraform {
  backend "s3" {
    bucket         = "company-terraform-state"
    key            = "production/terraform.tfstate"
    region         = "us-east-1"
    encrypt        = true
    dynamodb_table = "terraform-state-lock"
    # Versioning enabled on the S3 bucket
    # MFA delete enabled on the S3 bucket
  }
}

Plan/Preview Before Apply

Never let an AI agent run terraform apply directly. Always require a plan step first:

Safe workflow: plan, review, then apply
# Step 1: Generate the plan (safe - read-only operation)
terraform plan -out=tfplan

# Step 2: Review the plan output (human reads this)
terraform show tfplan

# Step 3: Only after human approval, apply the saved plan
terraform apply tfplan

# NEVER do this (skips review entirely):
# terraform apply -auto-approve  # DANGEROUS
Pulumi - Preview before deploying
# Step 1: Preview changes (safe - no modifications)
pulumi preview

# Step 2: After human review, deploy
pulumi up

# NEVER do this:
# pulumi up --yes --skip-preview  # DANGEROUS

Drift Detection and Reconciliation Safety

Drift detection identifies differences between your IaC definitions and actual cloud resources. This is important for AI agent safety because:

  • Detecting agent-made changes: If an agent modified resources outside of Terraform, drift detection will catch it
  • Preventing reconciliation disasters: If drift exists, a terraform apply might delete manually-created resources. Always review drift before applying
  • Audit trail: Drift reports provide evidence of unauthorized changes

Code Review Requirements for IaC Changes

Best Practice: Require pull request reviews for ALL IaC changes, even those generated by AI agents. Configure branch protection rules that require at least one approval from a designated infrastructure team member before merging any Terraform, Pulumi, or CloudFormation changes.
💡
Next Up: The next lesson covers cloud-native resource protection mechanisms - deletion protection flags, resource locks, and object locks that prevent destruction even when the caller has the correct permissions.

Ready to Go Deeper?

Live instructor-led courses from our partners. Affiliate disclosure.