Skip to content

Instantly share code, notes, and snippets.

@magnetikonline
Last active February 16, 2025 22:44
Show Gist options
  • Save magnetikonline/51bbb3de48dc4a10e11f38f9d911ac08 to your computer and use it in GitHub Desktop.
Save magnetikonline/51bbb3de48dc4a10e11f38f9d911ac08 to your computer and use it in GitHub Desktop.
Remove existing AWS CloudFormation stack, but retain all managed resources.

Delete CloudFormation stack - retaining resources

A guide for removing an existing CloudFormation stack - but retaining all managed resources.

First step - we need to get the CloudFormation stack into a state of DELETE_FAILED. This can be achieved by attempting stack delete with an IAM role that only has IAM action rights to cloudformation:DeleteStack and cloudformation:DescribeStackResources.

Create a new temporary IAM role with only the following allowed policy actions - for the rest of this guide that will be IAM role TEMP_CLOUDFORMATION_ROLE:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": [
        "cloudformation:DeleteStack",
        "cloudformation:DescribeStackResources",
        "iam:PassRole"
      ],
      "Effect": "Allow",
      "Resource": "*"
    }
  ]
}

...and the following trust relationship/assume role policy:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "sts:AssumeRole",
      "Effect": "Allow",
      "Principal": {
        "Service": "cloudformation.amazonaws.com"
      }
    }
  ]
}

Next, configure your AWS CLI via ~/.aws/config to include this new IAM role.

Important

Confirm you can successfully assume the temporary IAM role before attempting the failed delete operation - otherwise, you may successfully delete resources.

$ aws sts get-caller-identity --profile TEMP_CLOUDFORMATION_ROLE

{
  "UserId": "AIDXXXXXXXXXXXXXXXXXX",
  "Account": "1234567890",
  "Arn": "arn:aws:sts::1234567890:assumed-role/TEMP_CLOUDFORMATION_ROLE"
}

Now, proceed with the CloudFormation stack delete which will intentionally fail based on the IAM permissions set for the TEMP_CLOUDFORMATION_ROLE IAM role:

$ aws cloudformation delete-stack \
  --profile TEMP_CLOUDFORMATION_ROLE \
  --role-arn arn:aws:iam::1234567890:role/TEMP_CLOUDFORMATION_ROLE \
  --stack-name DELETE_THIS_STACK

The CloudFormation stack will now enter a DELETE_FAILED state.

Next, obtain a list of the logical resource IDs managed by the stack:

$ aws cloudformation describe-stack-resources \
  --profile TEMP_CLOUDFORMATION_ROLE \
  --stack-name DELETE_THIS_STACK \
  --output text \
  --query "join(' ',StackResources[].LogicalResourceId)"

Now delete the stack using the --retain-resources argument to aws cloudformation delete-stack - providing a space delimited list of logical resource IDs obtained above to retain:

$ aws cloudformation delete-stack \
  --profile TEMP_CLOUDFORMATION_ROLE \
  --retain-resources LOGICAL_RESOURCE_ID1 LOGICAL_RESOURCE_ID2 LOGICAL_RESOURCE_IDX \
  --role-arn arn:aws:iam::1234567890:role/TEMP_CLOUDFORMATION_ROLE \
  --stack-name DELETE_THIS_STACK

Finally, remove your temporary IAM role TEMP_CLOUDFORMATION_ROLE. Done!

Reference

@magnetikonline
Copy link
Author

I did exactly this process but my RDS database was deleted by cloudformation when deleting the stack with the temporary user :'(

@tgigli FWIW, did this today with an RDS database - it was retained, not dropped.

@martinhelfert
Copy link

martinhelfert commented Dec 19, 2023

@tgigli
You might have an IAM role attached to the stack (see stack info tab). This makes the deletion run with the role that is associated there, instead of the user role.
Append —role-arn NAME_OF_THE_TEMPORARY_ROLE to all cloudformation delete-stack commands. That worked in my case.
So basically, I just created the role from above and using my admin user with the —role-arn param on all delete-stack commands. This worked like a charm.

@magnetikonline
Copy link
Author

magnetikonline commented Dec 20, 2023

You might have an IAM role attached to the stack (see stack info tab). This makes the deletion run with the role that is associated there, instead of the user role.

@martinhelfert boom - I think you might have nailed it 👍

https://awscli.amazonaws.com/v2/documentation/api/latest/reference/cloudformation/delete-stack.html

If you don’t specify a value, CloudFormation uses the role that was previously associated with the stack. If no role is available, CloudFormation uses a temporary session that’s generated from your user credentials.

I might have to update this guide to use this arg (--role-arn) instead. Great callout 👍

@albertodiazdorado
Copy link

Would this work with resources that do not define a DeletionPolicy attribute, such as AWS::AutoScaling::AutoScalingGroup?

https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-autoscaling-autoscalinggroup.html

@magnetikonline
Copy link
Author

magnetikonline commented Jan 8, 2024

Thanks again @martinhelfert - have updated the instructions to use an IAM role (not user) - and make use of --role-arn with all aws cloudformation delete-stack commands for additional safety. I think that's great advice 👍.

Also noted the IAM role needs a assume role policy of:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "sts:AssumeRole",
      "Effect": "Allow",
      "Principal": {
        "Service": "cloudformation.amazonaws.com"
      }
    }
  ]
}

otherwise the use of --role-arn won't work.

@SamuelNeves
Copy link

It would be really usefull if AWS just give us an option like --not-delete-resources

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment