Skip to main content

05 - Drift Detection and Continuous Compliance Masterclass

Even when an organization deploys 100% of its cloud infrastructure through secure CI/CD pipelines, Infrastructure Drift occurs when manual changes ("Click-Ops"), emergency hotfixes, or out-of-band automated scripts modify live cloud resources directly in the cloud provider console or API.

Drift creates critical security blind spots: unauthorized security group modifications, publicly exposed storage buckets, and disabled logging controls bypass git pull request reviews and CI/CD SAST scanners.

This chapter covers technical strategies for continuous drift detection, cloud-native compliance guardrails (AWS Config, Azure Policy), and automated event-driven remediation architectures.


🚨 Understanding Infrastructure Drift

Infrastructure Drift represents the desynchronization between Declared State (Git source code), Tracked State (Terraform .tfstate), and Actual Real-World State (Live Cloud APIs).

Common Causes of Drift & Security Impacts

Drift CauseReal-World ScenarioSecurity Impact
Emergency HotfixEngineer opens SSH port 22 to 0.0.0.0/0 via AWS Console during a midnight outage and forgets to revert.Unprotected management port exposed to internet scans indefinitely.
Shadow ITDeveloper creates an unencrypted S3 bucket directly in console for quick file transfers.Storage lacks encryption, logging, and public access blocks; completely invisible to Git repository audits.
Console Policy EditSecurity auditor manually toggles an IAM policy to test access permissions.IAM role granted over-privileged access without peer review or record in commit history.

🛠️ Automated Drift Detection Technical Strategies

Strategy 1: CI/CD Pipeline Scheduled terraform plan

Run terraform plan on a cron-scheduled pipeline (e.g., nightly at 02:00 UTC). Use the -detailed-exitcode flag to detect drift programmatically.

Detailed Exit Codes:

  • 0: Succeeded with empty diff (No drift detected).
  • 1: Error during execution.
  • 2: Succeeded with non-empty diff (Drift detected).
#!/usr/bin/env bash
# scheduled-drift-check.sh

echo "[+] Initializing Terraform..."
terraform init -backend-config="bucket=enterprise-tf-state-us-east-1-prod"

echo "[+] Running Terraform Plan Drift Check..."
terraform plan -detailed-exitcode -no-color > drift_report.txt
EXIT_CODE=$?

if [ $EXIT_CODE -eq 2 ]; then
echo "::error::CRITICAL DRIFT DETECTED! Live cloud infrastructure differs from Git baseline!"
# Trigger alert to Security Operations (Slack / PagerDuty / Jira)
curl -X POST -H 'Content-type: application/json' \
--data '{"text":"🚨 *Security Drift Alert*: Live Cloud Resources have drifted from Terraform baseline!"}' \
"$SLACK_WEBHOOK_URL"
exit 2
elif [ $EXIT_CODE -eq 0 ]; then
echo "[+] Zero drift detected. Infrastructure is perfectly synchronized."
exit 0
else
echo "[!] Error running terraform plan."
exit 1
fi

Strategy 2: Specialized Drift Scanning with driftctl

driftctl is an open-source tool that measures infrastructure drift by comparing live cloud accounts directly against Terraform state files, identifying unmanaged "shadow" cloud resources.

# Install driftctl
curl -L https://github.com/snyk/driftctl/releases/latest/download/driftctl_linux_amd64 -o driftctl
chmod +x driftctl

# Run drift scan against AWS infrastructure and remote S3 state
AWS_REGION=us-east-1 driftctl scan \
--from tfstate+s3://enterprise-tf-state-us-east-1-prod/production/terraform.tfstate \
--output json://drift-report.json

Driftctl Ignore File (.driftignore)

Exclude noisy or non-security-critical resources from drift reports:

# .driftignore
# Ignore ephemeral auto-scaling EC2 instances
aws_instance.autoscaling_*

# Ignore temporary CloudWatch log streams
aws_cloudwatch_log_stream.*

Strategy 3: AWS CloudFormation Native Drift Detection

AWS CloudFormation provides native drift detection APIs that calculate whether resources in a deployed stack have been modified out-of-band:

# Initiate drift detection scan on a CloudFormation stack
aws cloudformation detect-stack-drift --stack-name ProductionCoreNetworkStack

# Retrieve drift status report
aws cloudformation describe-stack-resource-drifts \
--stack-name ProductionCoreNetworkStack \
--stack-resource-drift-status-filters MODIFIED DELETED

🛡️ Cloud-Native Continuous Compliance (AWS Config & CSPM)

While IaC SAST scans code before deployment, Cloud Security Posture Management (CSPM) and cloud-native services continuously audit resources after deployment.

Provisioning AWS Config Rules via Terraform

Deploy AWS Config rules directly using Terraform to enforce continuous compliance against CIS AWS Foundations Benchmarks:

# aws-config-compliance/main.tf

# Enable AWS Config Recorder
resource "aws_config_configuration_recorder" "main" {
name = "enterprise-config-recorder"
role_arn = aws_iam_role.config_role.arn

recording_group {
all_supported = true
include_global_resource_types = true
}
}

# Config Rule 1: Enforce S3 Public Read Prohibited
resource "aws_config_config_rule" "s3_public_read" {
name = "s3-bucket-public-read-prohibited"
description = "Checks that S3 buckets do not allow public read access."

source {
owner = "AWS"
source_identifier = "S3_BUCKET_PUBLIC_READ_PROHIBITED"
}

depends_on = [aws_config_configuration_recorder.main]
}

# Config Rule 2: Enforce Encrypted EBS Volumes
resource "aws_config_config_rule" "ebs_encryption" {
name = "encrypted-volumes"
description = "Checks that EBS volumes are encrypted at rest."

source {
owner = "AWS"
source_identifier = "ENCRYPTED_VOLUMES"
}

depends_on = [aws_config_configuration_recorder.main]
}

# Config Rule 3: Enforce Restricted SSH Ingress (Port 22)
resource "aws_config_config_rule" "restricted_ssh" {
name = "restricted-common-ports"
description = "Checks whether security groups allow unrestricted incoming traffic to high-risk ports."

source {
owner = "AWS"
source_identifier = "INCOMING_SSH_DISABLED"
}

depends_on = [aws_config_configuration_recorder.main]
}

⚡ Automated Event-Driven Remediation Architecture

When unauthorized drift or a non-compliant state is detected in real time, manual remediation creates delays. An Event-Driven Remediation Architecture detects cloud modifications instantly and automatically reverts non-compliant settings.

Python Lambda Auto-Remediation Code

Below is an AWS Lambda Python script triggered by EventBridge when an S3 bucket is modified to allow public access:

# lambda_remediate_s3_public.py
import json
import boto3
import os
import logging

logger = logging.getLogger()
logger.setLevel(logging.INFO)

s3_client = boto3.client('s3')

def lambda_handler(event, context):
"""
Automatically enforces S3 Public Access Block when an unauthorized change is detected.
"""
logger.info(f"Received Event: {json.dumps(event)}")

# Extract bucket name from CloudTrail event details
try:
bucket_name = event['detail']['requestParameters']['bucketName']
except KeyError:
logger.error("Could not extract bucketName from event payload.")
return {"status": "error", "reason": "invalid_event"}

logger.warning(f"Enforcing automated public access block on drifted bucket: {bucket_name}")

# Apply strict Public Access Block
response = s3_client.put_public_access_block(
Bucket=bucket_name,
PublicAccessBlockConfiguration={
'BlockPublicAcls': True,
'IgnorePublicAcls': True,
'BlockPublicPolicy': True,
'RestrictPublicBuckets': True
}
)

logger.info(f"Successfully remediated S3 bucket {bucket_name}. Response: {response}")

return {
"status": "remediated",
"bucket": bucket_name
}

[!IMPORTANT] Key Takeaway: Preventing cloud incidents requires pairing pre-deployment CI/CD SAST scanning with continuous post-deployment drift detection (driftctl / terraform plan) and automated event-driven remediation guardrails.

Next, move to Chapter 06: Hands-On Lab.

Share this guide