← Recipes

阅读中文版本

Detect and Report CloudFormation Stack Drift

Run drift detection on a schedule, parse resource-level results, and alert on the specific resources changed outside the stack.

~30 minawscloudformationdrift

Task

Know which stack resources were modified outside CloudFormation before the next update silently reverts them.

When to use this

A support engineer changes a security group rule in the console to unblock a customer and never reverts it; the next stack update removes the rule and the customer breaks again.

Prerequisites

  • AWS CLI v2 with CloudFormation permissions
  • Stacks whose resource types support drift detection
  • A scheduled job with an alert channel

Steps

1. Start drift detection for the stack and wait for it to finish.

aws cloudformation detect-stack-drift --stack-name payments-prod && aws cloudformation wait stack-drift-detection-complete --stack-name payments-prod

Expected output: Detection starts and the waiter returns without an error once it completes.

2. Read the stack-level drift status after detection.

aws cloudformation describe-stacks --stack-name payments-prod --query 'Stacks[0].DriftInformation.StackDriftStatus' --output text

Expected output: The status is DRIFTED when at least one resource differs and IN_SYNC otherwise.

3. List only the resources that were modified or deleted outside the stack.

aws cloudformation describe-stack-resource-drifts --stack-name payments-prod --stack-resource-drift-status-filters MODIFIED DELETED --query 'StackResourceDrifts[].{Logical:LogicalResourceId,Type:ResourceType,Status:StackResourceDriftStatus}' --output table

Expected output: A table names the changed security group and any deleted resource by logical ID.

4. Make the scheduled job alert only when the drift count is non-zero.

aws cloudformation describe-stack-resource-drifts --stack-name payments-prod --query 'length(StackResourceDrifts[?StackResourceDriftStatus!=`IN_SYNC`])' --output text

Expected output: A non-zero count feeds the alert; zero keeps the nightly run silent.

Troubleshooting

Problem

A resource reports NOT_CHECKED

Solution

Nested stacks, custom resources, and some resource types are unsupported; read the status reason and track those resources separately.

Problem

Everything shows drift right after a deploy

Solution

Detection can run before the update settles; wait for UPDATE_COMPLETE and run detection again.

Limitations

  • Drift detection compares declared template properties, not runtime configuration or data.
  • Resources deleted from the template are no longer tracked, so their drift is invisible.

Console changes are invisible until the next deploy

CloudFormation records what it created, not what currently exists. When someone edits a security group or resizes an instance in the console, the stack believes the template is still reality, and the next update quietly restores the template. That is usually the right behavior, but it means an emergency change can be reverted in the middle of a release unless the team knows it exists. Drift detection compares each supported resource’s current properties against the template and reports what changed.

Run detection, then read it at resource level

Stack-level status is not enough to act on; the useful output is the per-resource drift list. Run detect-stack-drift, wait for completion, then query describe-stack-resource-drifts with a filter so the alert contains the logical IDs and property differences. Keep the detection in a scheduled job instead of on every deploy, because detection has a cost and a rate limit per account. Alert on a non-zero drifted count, and route the alert to the team that owns the stack.

aws cloudformation describe-stack-resource-drifts --stack-name payments-prod \
  --stack-resource-drift-status-filters MODIFIED DELETED \
  --query 'StackResourceDrifts[].{Logical:LogicalResourceId,Type:ResourceType,Status:StackResourceDriftStatus}' \
  --output table

Close the loop

Every drift finding has two possible resolutions: codify the change in the template, or revert it. Do one of them within the same working day, or the finding becomes permanent noise. Add a comment to the stack template explaining intentional differences, and review detection coverage quarterly, since unsupported resource types silently report NOT_CHECKED. For nested stacks, run detection on each child stack, because parent-level detection does not descend reliably.