โšก Onwuachi Control Plane

Aws CloudFormation Drift Detection

Overview

AWS CloudFormation drift detection identifies whether resources managed by a CloudFormation stack have been changed outside of CloudFormation and no longer match the configuration defined by the stack template.

CloudFormation maintains an expected configuration based on the template used to create or update the stack. If an administrator changes a resource directly through the AWS Console, AWS CLI, SDK, Terraform, or another management tool, the actual resource configuration can become different from the configuration CloudFormation expects.

This difference is known as drift.

CloudFormation does not continuously reconcile every resource back to the template. A resource can therefore be changed outside CloudFormation without immediately causing the stack’s normal lifecycle status to change.

Drift detection provides a way to explicitly compare the expected configuration with the actual configuration.

Why It Matters

Infrastructure as code is most effective when the code and the deployed environment remain consistent.

For example, a CloudFormation template might define a Security Group that allows SSH access only from an internal network:

SecurityGroupIngress:
  - IpProtocol: tcp
    FromPort: 22
    ToPort: 22
    CidrIp: 10.50.0.0/16

An administrator might later modify the Security Group directly through the AWS Console and change the rule to:

0.0.0.0/0

The AWS resource has now changed, but the CloudFormation template has not.

The infrastructure has drifted.

This matters because the deployed environment may no longer represent the approved infrastructure definition.

Drift detection can help identify:

For compliance programs such as SOC 2 or HITRUST, drift detection can support configuration-management and change-control processes by helping demonstrate that infrastructure is periodically checked for unexpected changes.

Drift detection itself, however, is not a complete compliance control. It is one mechanism that can contribute to a broader change-management and infrastructure-governance process.


Where It Fits

CloudFormation drift detection fits into the infrastructure-as-code lifecycle after resources have been deployed.

A simplified workflow looks like this:

CloudFormation Template
        |
        | Defines expected configuration
        v
CloudFormation Stack
        |
        | Provisions and manages
        v
AWS Resources
        |
        | Out-of-band change
        | Console / CLI / SDK / Other Tool
        v
Actual Resource State
        |
        | Expected != Actual
        v
Potential Drift
        |
        | Explicit drift detection
        v
CloudFormation Drift Status
        |
        +----------------------+
        |                      |
        v                      v
     IN_SYNC                DRIFTED
                               |
                               v
                         Investigation
                               |
                 +-------------+-------------+
                 |                           |
                 v                           v
          Revert change              Update IaC
          to expected state          and/or stack

The important point is that CloudFormation does not automatically perform this comparison continuously.

The drift detection operation must be initiated explicitly, either manually or through automation.

A production environment can automate this process using services such as EventBridge, Lambda, SNS, or an incident-management workflow.


The Big Picture

The CloudFormation drift model can be understood as three separate concepts:

1. CloudFormation Template
   --------------------------------
   What the infrastructure should be

2. Actual AWS Resource
   --------------------------------
   What the infrastructure currently is

3. Drift Detection
   --------------------------------
   The comparison between expected and actual

The result can be represented as:

                CloudFormation
                Template
                    |
                    | Expected State
                    v
              +-------------+
              |             |
              | Comparison  |
              |             |
              +-------------+
                    ^
                    |
                    | Actual State
                    |
              AWS Resource

If the expected and actual configurations match:

Expected State == Actual State
                |
                v
             IN_SYNC

If they differ:

Expected State != Actual State
                |
                v
             DRIFTED

Drift detection is therefore a detection mechanism, not a remediation mechanism.

CloudFormation identifies the difference, but it does not automatically decide whether the manual change was intentional or unauthorized.


Core Concepts

Expected State vs. Actual State

CloudFormation maintains an expected configuration for resources based on the stack template.

The actual resource exists in AWS and can potentially be modified independently.

For example:

CloudFormation Template
-----------------------
SSH allowed from:
10.50.0.0/16


Actual Security Group
---------------------
SSH allowed from:
0.0.0.0/0

The resource is now different from the expected configuration. That is drift.

Stack Lifecycle Status vs. Drift Status

One of the most important concepts is that a stack’s normal lifecycle status and its drift status are different things.

A stack might show:

StackStatus: CREATE_COMPLETE

while its drift status is:

StackDriftStatus: DRIFTED

The stack successfully completed its original creation. That does not mean that the current AWS resources still match the CloudFormation template.

Stack Lifecycle Status        Drift Status
-----------------------       ------------
CREATE_COMPLETE                IN_SYNC
UPDATE_COMPLETE                DRIFTED
UPDATE_FAILED                  NOT_CHECKED
DELETE_COMPLETE

A successful CloudFormation deployment therefore does not guarantee that the environment remains synchronized forever.

Drift Detection Is Not Automatic Reconciliation

CloudFormation should not be thought of as continuously reconciling resources in the same way that Kubernetes controllers continuously work toward a desired state.

A manual change can remain in place until:

  1. Drift detection is performed.
  2. The drift is identified.
  3. Someone investigates the change.
  4. The organization determines whether the change was intentional.
  5. The configuration is remediated if necessary.

Resource Drift Status

CloudFormation can report drift at the resource level. Common statuses include:

StatusMeaning
IN_SYNCActual resource configuration matches expected configuration
MODIFIEDOne or more properties differ from the expected configuration
DELETEDThe resource expected by CloudFormation no longer exists
NOT_CHECKEDDrift detection has not been performed for the resource

The stack-level drift status provides an overall view, while resource-level drift information helps identify exactly what changed.

Drift Detection Is Asynchronous

The AWS CLI command aws cloudformation detect-stack-drift does not immediately return the final drift results. Instead, CloudFormation starts an asynchronous detection operation and returns a StackDriftDetectionId.

detect-stack-drift
        |
        v
StackDriftDetectionId
        |
        v
describe-stack-drift-detection-status
        |
        v
DETECTION_IN_PROGRESS  โ†’  DETECTION_COMPLETE
        |
        v
describe-stack-resource-drifts

A script should not assume that calling detect-stack-drift means the results are immediately available.


Real-World Example

A CloudFormation stack creates an EC2 Security Group. The template allows SSH only from an internal network (10.50.0.0/16). The stack is created successfully.

An administrator later manually changes the Security Group to allow 0.0.0.0/0 instead. The Security Group is now different from the CloudFormation template, but the stack’s lifecycle status may still show CREATE_COMPLETE.

Running drift detection allows CloudFormation to identify the difference โ€” this exact scenario is walked through hands-on below.


Hands-On Lab

This lab creates a simple Security Group, manually changes it outside CloudFormation, detects the resulting drift, and cleans up. A Security Group is used because it has no hourly infrastructure charge โ€” the full exercise runs at $0.

Step 1 โ€” Create the template and stack

cat > /tmp/drift-test.yaml << 'EOF'
AWSTemplateFormatVersion: '2010-09-09'
Description: CloudFormation drift detection demo

Resources:
  DemoSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Drift detection demo
      VpcId: <your-vpc-id>
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 22
          ToPort: 22
          CidrIp: 10.50.0.0/16
EOF

aws cloudformation create-stack \
  --stack-name drift-demo \
  --template-body file:///tmp/drift-test.yaml \
  --region us-east-1

Check status until CREATE_COMPLETE:

aws cloudformation describe-stacks \
  --stack-name drift-demo --region us-east-1 \
  --query 'Stacks[0].StackStatus'

Step 2 โ€” Retrieve the physical Security Group ID

aws cloudformation describe-stack-resources \
  --stack-name drift-demo --region us-east-1 \
  --query 'StackResources[0].PhysicalResourceId' --output text

Step 3 โ€” Verify the original configuration

aws ec2 describe-security-groups \
  --group-ids <sg-id> --region us-east-1 \
  --query 'SecurityGroups[0].IpPermissions'

Confirm the rule shows 10.50.0.0/16 โ€” expected and actual should be in sync here.

Step 4 โ€” Manually create drift

aws ec2 revoke-security-group-ingress \
  --group-id <sg-id> --protocol tcp --port 22 \
  --cidr 10.50.0.0/16 --region us-east-1

aws ec2 authorize-security-group-ingress \
  --group-id <sg-id> --protocol tcp --port 22 \
  --cidr 0.0.0.0/0 --region us-east-1

Step 5 โ€” Confirm the stack lifecycle status is unaffected

aws cloudformation describe-stacks \
  --stack-name drift-demo --region us-east-1 \
  --query 'Stacks[0].StackStatus'

Still reports CREATE_COMPLETE โ€” proof that drift is invisible until explicitly checked.

Step 6 โ€” Start drift detection

aws cloudformation detect-stack-drift \
  --stack-name drift-demo --region us-east-1

Returns a StackDriftDetectionId.

Step 7 โ€” Check detection progress

aws cloudformation describe-stack-drift-detection-status \
  --stack-drift-detection-id <id> --region us-east-1

Wait for DetectionStatus: DETECTION_COMPLETE before querying results.

Step 8 โ€” Check the stack drift status

aws cloudformation describe-stacks \
  --stack-name drift-demo --region us-east-1 \
  --query 'Stacks[0].{StackStatus:StackStatus,DriftStatus:DriftInformation.StackDriftStatus}'

Expected result:

{
    "StackStatus": "CREATE_COMPLETE",
    "DriftStatus": "DRIFTED"
}

Step 9 โ€” Identify the drifted resource

aws cloudformation describe-stack-resource-drifts \
  --stack-name drift-demo --region us-east-1 \
  --query 'StackResourceDrifts[].{LogicalId:LogicalResourceId,Status:StackResourceDriftStatus,Actual:ActualProperties,Expected:ExpectedProperties}'

Reports StackResourceDriftStatus: MODIFIED, with Expected showing 10.50.0.0/16 and Actual showing 0.0.0.0/0.

Step 10 โ€” Remediate

Option 1 โ€” Revert the resource (if the change was unauthorized):

aws ec2 revoke-security-group-ingress \
  --group-id <sg-id> --protocol tcp --port 22 \
  --cidr 0.0.0.0/0 --region us-east-1

aws ec2 authorize-security-group-ingress \
  --group-id <sg-id> --protocol tcp --port 22 \
  --cidr 10.50.0.0/16 --region us-east-1

Option 2 โ€” Update the template (if the change was intentional and should become the new approved state).

Option 3 โ€” Investigate first โ€” who made the change, why, was it approved, will reverting cause an outage. Drift is a signal that expected and actual disagree; the correct remediation depends on why.

Step 11 โ€” Clean up

aws cloudformation delete-stack \
  --stack-name drift-demo --region us-east-1

Confirm removal โ€” the describe-stacks call should error with “does not exist.”


Engineering Analogy

CloudFormation Drift vs. Terraform Plan

Terraform                          CloudFormation
---------                          --------------
Terraform Configuration            CloudFormation Template
        |                                  |
        v                                  v
terraform plan                     Deployed AWS Resources
        |                                  |
  Compare desired config             detect-stack-drift
  with Terraform state                    |
  + refresh/query infra                   v
        |                          Drift Report
        v
Proposed Changes

Terraform plan is part of the normal planning workflow. CloudFormation drift detection is an explicit check for differences between a CloudFormation-managed resource and its expected configuration.

They should not be treated as exact equivalents. Terraform has a broader planning workflow that evaluates proposed changes before applying them. CloudFormation drift detection specifically answers whether supported resource properties have diverged from the expected CloudFormation configuration.

CloudFormation Drift vs. Kubernetes Reconciliation

Kubernetes                         CloudFormation
-----------                        --------------
Desired State                      Expected State
     |                                    |
     v                                    v
Controller                          AWS Resource
     |                                    |
     v                              Out-of-band change
Actual State                              |
     |                                    v
Difference? --Yes--> Reconcile      Actual State
     |                                    |
     No -> Continue               No automatic reconciliation
                                          |
                                          v
                                  Drift Detection Requested
                                          |
                                          v
                                  Difference Reported

This is why drift detection should be viewed as detection and visibility, not automatic continuous enforcement.


Best Practices


Common Mistakes


Pro Tip

Always remember: “CREATE_COMPLETE” does not mean “IN_SYNC.”

A CloudFormation stack can have successfully completed its last lifecycle operation while the actual resources have subsequently changed. For operational troubleshooting, think in two dimensions โ€” did CloudFormation successfully deploy the stack (StackStatus), and does the deployed infrastructure still match the template (StackDriftStatus)?

A practical investigation workflow:

  1. Check StackStatus
  2. Check StackDriftStatus
  3. Identify drifted resources
  4. Compare expected vs. actual properties
  5. Review CloudTrail for the change
  6. Check change tickets / deployment history
  7. Determine whether the change was intentional
  8. Remediate through the approved process
  9. Re-run drift detection

Key Takeaways


Related Articles


References

System Context

โ† Back to Kb