Protecting Critical SNS Topics From Deletion

stops even all-powerful IAM admin users in their tracks

I run some SNS topics as a public service where anybody can subscribe their own AWS Lambda functions, SQS queues, and email addresses.

If one of these SNS topics were to be accidentally deleted, I could recreate it with the same name and ARN. However, all of the existing user subscriptions would be lost and I would not be able to restore them myself. Each of the hundreds of users would have to figure out what happened and re-subscribe the appropriate targets with the correct permissions.

I don’t want these SNS topics to be deleted. Ever.

Retention Policy

Where the SNS Topics are created using CloudFormation, I put in a basic level of protection by specifying the following attribute on both the AWS::SNS::Topic and AWS::SNS::TopicPolicy resources:

"DeletionPolicy" : "Retain"

This tells CloudFormation to leave the SNS topic and topic policy untouched if the CloudFormation template itself is deleted. I’ve tested this and it works well.

However, I also want to protect the SNS Topic from accidental deletion in the AWS console, aws-cli, or other tools.

Deny Delete

I found that I can extend the SNS topic policy with a Deny statement for sns:DeleteTopic and this blocks delete-topic attempts even with an IAM user that has full admin privileges.

Simply add a statement to the list in the policy document as demonstrated here:

...
"PolicyDocument" : {
  "Version": "2008-10-17",
  "Statement": [
    ...existing policy statements...,
    {
      "Sid": "DenyTopicDelete",
      "Effect": "Deny",
      "Principal": {
        "AWS": "*"
      },
      "Action": [
        "sns:DeleteTopic"
      ],
      "Resource": "*"
    }
...

You can specify the specific SNS Topic ARN as the "Resource" value if you like being explicit.

To reduce confusion, you may also remove "sns:DeleteTopic" from the "Allow" policy statement where it is by default, but the "Deny" does override it.

Delete Override

Unfortunately (or fortunately) this doesn’t completely prevent a determined admin from being able to take appropriate action to remove an SNS topic that has been set up this way. It is primarily intended to prevent accidental deletion and to ensure that any deletion is confirmed by explicit and conscious steps.

If you create an SNS topic policy with this statement that denies all delete attempts, and you really need to delete the SNS topic, then you should first modify the topic policy. Remove the deletion protection statement, then delete the topic.

I haven’t tried to find a way to prevent an admin from modifying the SNS topic policy. I’m a little afraid of what would happen if that was successful, though I guess we always have the AWS root account as a safety backup.

Speaking of which…

Root Account

It is important to note that this approach does nothing to stop the AWS root account from deleting the SNS topic. If you use the email address and password to sign in on the console, or use root account credentials in the aws-cli, then you are unprotected. That account cannot be restricted.

Amazon recommends that you lock away the root account keys. I recommend that you go further and throw away the password for the root account.