Delete CloudFormation Stack while Retaining Resources
This post will be useful for you if you want to delete a CloudFormation stack without deleting all or some of its resources, but you don’t want to or cannot use the standard approach with deletion policy which requires updating the stack template.
The Challenge
If you take a look at cloudformation delete-stack AWS CLI command, you’ll find that there’s a parameter --retain-resources
which allows retaining or skipping, instead of deleting, resources when the stack is deleted. However, for some reason, it can only be used for resources in DELETE_FAILED
state.
The Trick
To leverage the --retain-resources
parameter, we need to induce the DELETE_FAILED
state for the resources we want to retain. Here’s how to achieve this safely:
- Create an IAM role with permissions to delete the stack but without permissions to delete specific resources you want to keep.
- Attempt to delete the CloudFormation stack using this IAM role.
- The deletion attempt will fail for the resources the role can’t delete, marking them with
DELETE_FAILED
status. - You can then use the
--retain-resources
parameter to keep these resources while deleting the stack.
This approach allows you to selectively retain resources without modifying the original stack template.
The Process
With this strategy in mind, here’s the step-by-step process to selectively delete a CloudFormation stack:
- Create an IAM role that can delete the stack but lacks permissions to delete the resources you want to retain.
- Attempt to delete the stack using this role, which will result in
DELETE_FAILED
state for the desired resources. - Use AWS CLI to delete the stack again, this time with the
--retain-resources "ResourceLogicalId"
parameter. Replace “ResourceLogicalId” with the logical ID of the resource(s) you want to keep. You can list multiple resources by separating their IDs with spaces. - If not all desired resources achieve the
DELETE_FAILED
state on the first attempt, repeat steps 2 and 3. This may be necessary depending on CloudFormation’s deletion logic.
Automation Script
Below is a Bash script that automates this process:
#!/usr/bin/env bash
stack_name="$STACK_NAME"
stack_role_arn="$STACK_ROLE_ARN"
echo "Initial delete attempt"
aws cloudformation delete-stack --stack-name "$stack_name" \
--role-arn "$stack_role_arn"
sleep 5
for i in {1..3}
do
echo "Delete iteration attempt $i"
failed_resources=$(aws cloudformation list-stack-resources \
--stack-name "$stack_name" \
--query "StackResourceSummaries[?ResourceStatus=='DELETE_FAILED'].LogicalResourceId" \
--output text)
echo "Skipping failed resources: $failed_resources"
aws cloudformation delete-stack --stack-name "$stack_name" \
--role-arn "$stack_role_arn" --retain-resources $failed_resources
sleep 5
done
Pay attention that the script expects 2 environment variables to be set: STACK_NAME
and STACK_ROLE_ARN
.
You can run it like so:
STACK_NAME="your-stack-name" \
STACK_ROLE_ARN="arn:aws:iam::your-account-id:role/stack-role-name" \
./this-script.sh
I’ve used this script on more than 10 different stacks and 2-3 iterations is usually enough. However, if you need more iterations, just modify the for i in {1..3}
line.
Lastly, make sure to test this in a test environment first!