How to Create AWS SNS Topic Policy using CloudFormation
Dear reader, I hope you are doing great. In one of my previous post, I explained how to use CloudFormation to create SNS topic and subscription.
In today’s post, I am here to help you create SNS Topic Policy using CloudFormation. By the end of this tutorial, you should be able to apply an access policy or topic policy to an SNS topic(or list of topics) using CloudFormation.
Let’s start with understanding amazon SNS Topic Policy !!!
What is Amazon SNS Topic Policy?
Amazon SNS Topic Policy or Access Policy is a resource bases policy which gets applied on an SNS topic resource. It basically defines who can publish or subscribe or do other actions to your topic.
Just to let you know, Amazon SNS adds a default policy to all the newly created topic and it looks like below-
{
"Version": "2008-10-17",
"Id": "__default_policy_ID",
"Statement": [
{
"Sid": "__default_statement_ID",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": [
"SNS:GetTopicAttributes",
"SNS:SetTopicAttributes",
"SNS:AddPermission",
"SNS:RemovePermission",
"SNS:DeleteTopic",
"SNS:Subscribe",
"SNS:ListSubscriptionsByTopic",
"SNS:Publish"
],
"Resource": "arn:aws:sns:ap-south-1:123456789012:test",
"Condition": {
"StringEquals": {
"AWS:SourceOwner": "123456789012"
}
}
}
]
}
If you look closely on above policy, you will see by default only the topic owner can publish or subscribe to the topic.
This is the default policy. However, you can change it as per your requirement. Here are few example use-cases of SNS topic policies: SNS topic policy use-cases
When to use SNS Access Policy?
Ideally, you can use IAM policies or SNS access policy or both to provide permission to your users to be able to access your topics . However, SNS access policy or topic policy comes really handy, when it comes to giving cross account access to your topic.
For example- you can create an access policy on your topic in Account A to allow another account B to publish and subscribe to topic in Account A.
Alright?
Okay !!!
I guess, you have got an idea about SNS topic policies. So can we go ahead and see how to create an SNS Topic Policy using CloudFormation?
Let’s start 🙂
Steps to Create AWS SNS Topic Policy using CloudFormation?
- Provide proper permission to your user/role
- Prepare policy for your use-case
- Prepare the template
- Create a stack using prepared template
- Validate the applied policy in SNS console
Let’s see the step by step instruction to create AWS SNS topic policy using CloudFormation.
Step 1: Provide proper permission to your user/role
- If you are not an admin user, you should explicitly provide these permission for your user/role that will be used to create this CloudFormation stack.
- sns:CreateTopic
- sns:DeleteTopic
- sns:SetTopicAttributes
- Additionally, the user will also need cloudformation:* to be able to do CloudFormation stack creation, updation , deletion etc.
Important Note: If you are unable to figure out correct permission in the beginning, you can use sns:*. However, keep in mind that, it’s not safe to allow all action and you should only use it till you find correct set of permission.
Step 2: Prepare policy for your use-case
Once you have proper permission, It’s time to prepare the policy that you want to apply to your SNS topic. You can either craft permission yourself or go to Policy Generator to generate a policy using GUI.
Use-case that we will implement is to allow a user to be able to publish and subscribe on specified topic.
Go to Policy Generator –> Select Policy Type as SNS Topic Policy –> Provide Permission Details –> Click Add Statement –> Generate Policy
Permission/Statement Details:
- Effect : Allow
- Principal: arn:aws:iam::123456789012:user/username
- AWS Service: Amazon SNS(Preselected)
- Actions:
- Publish
- Subscribe
- Amazon Resource Name(ARN): arn:aws:sns:ap-south-1:123456789012:topicname
And you will have a policy like-
{
"Id": "Policy1643807614413",
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1643807474528",
"Action": [
"sns:Publish",
"sns:Subscribe"
],
"Effect": "Allow",
"Resource": "arn:aws:sns:ap-south-1:123456789012:test",
"Principal": {
"AWS": [
"arn:aws:iam::123456789012:user/test"
]
}
}
]
}
This policy allows specified actions to user test which has ARN like below-
arn:aws:iam::123456789012:user/test
You may decide to give permission to other accounts. In that case you can mention the principal like below.
"Principal": {
"AWS": "123456789012"
}
Important Note: Please note that in above policy, I have specified dummy account Id and username due to security reasons. Please make sure to use correct one otherwise your policy creation will fail with Invalid parameter: Policy Error: PrincipalNotFound error
Step 3: Prepare the template
You can use YAML or JSON for your template. I prefer YAML for writing my templates. But don’t worry, If you want it in JSON, I will provide JSON template as well.
To apply a topic policy or access policy to an SNS topic, we use AWS::SNS::TopicPolicy resource.
Type: AWS::SNS::TopicPolicy
Properties:
PolicyDocument: Json
Topics:
- String
Explanation –
- PolicyDocument is the actual policy that you want to apply to topic
- Topics parameter takes the ARN of all the topics to which you want to add the policy
Note: If you are defining the topic in the same template like me, use !Ref as using !Ref on topic returns topic ARN.
Template to Create AWS SNS Topic Policy using CloudFormation : YAML
In this template, we are creating an SNS named demo-topic. After the creation of topic, we are applying a policy to the same topic to allow user test to publish and subscribe to the topic.
AWSTemplateFormatVersion: 2010-09-09
Description: AWS CloudFormation Template to create an SNS topic and apply an access policy
Parameters:
TopicName:
Type: String
Description: Topic Name
Default: demo-topic
UserArn:
Type: String
Description: User to which SNS will allow perfoming actions
Default: arn:aws:iam::123456789012:user/test
Email:
Type: String
Description: EmailId
Default: [email protected]
Resources:
DemoTopic:
Type: AWS::SNS::Topic
Properties:
TopicName: TestTopic
Subscription:
- Endpoint: !Ref Email
Protocol: email
DemoTopicPolicy:
Type: AWS::SNS::TopicPolicy
Properties:
PolicyDocument:
Id: MyDemoTopicPolicy
Version: '2012-10-17'
Statement:
- Sid: Stmt1643807474528
Effect: Allow
Principal:
AWS: !Ref UserArn
Action:
- sns:Publish
- sns:Subscribe
Resource: !Ref DemoTopic
Topics:
- !Ref DemoTopic
Note: When you want to apply policy to multiple topic, make your Topics parameter like below. Also, you can use your existing topics as well. All you need is the ARN of existing topic.
Topics:
- !Ref DemoTopic
- !Ref AnotherTopic
- arn:aws:sns:ap-south-1:123456789012:existingtopic
Template to Create AWS SNS Topic Policy using CloudFormation: JSON
{
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "AWS CloudFormation Template to create an SNS topic and apply an access policy",
"Parameters": {
"TopicName": {
"Type": "String",
"Description": "Topic Name",
"Default": "demo-topic"
},
"UserArn": {
"Type": "String",
"Description": "User to which SNS will allow perfoming actions",
"Default": "arn:aws:iam::123456789012:user/test"
},
"Email": {
"Type": "String",
"Description": "EmailId",
"Default": "[email protected]"
}
},
"Resources": {
"DemoTopic": {
"Type": "AWS::SNS::Topic",
"Properties": {
"TopicName": "TestTopic",
"Subscription": [
{
"Endpoint": {
"Ref": "Email"
},
"Protocol": "email"
}
]
}
},
"DemoTopicPolicy": {
"Type": "AWS::SNS::TopicPolicy",
"Properties": {
"PolicyDocument": {
"Id": "MyDemoTopicPolicy",
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1643807474528",
"Effect": "Allow",
"Principal": {
"AWS": {
"Ref": "UserArn"
}
},
"Action": [
"sns:Publish",
"sns:Subscribe"
],
"Resource": {
"Ref": "DemoTopic"
}
}
]
},
"Topics": [
{
"Ref": "DemoTopic"
}
]
}
}
}
}
Step 4: Create the Stack using prepared template
Now, we know the basics and we have the template so let’s go and create the stack.
- Grab the YAML or JSON template from above as per your convenience.
- Change the parameters as per your requirement specially change the user to actual user or principal you want you SNS access policy to apply
- Save the template with .yml or .json as per the choice of template and follow below steps.
- Login to AWS Management Console, navigate to CloudFormation and click on Create stack
- Click on “Upload a template file”, upload your saved .yml or .json file and click Next
- Enter the stack name and click on Next. In configuration, keep everything as default and click on Next.
- In the events tab of stack, you can view the status. Once, successful, we will verify the policy
Step 5: Validate the applied policy in SNS console
Go to SNS, Click on your topic name
Go to Access Policy tab
You should be able to see the applied policy like below.
Congratulations !!!
You have successfully applied the access policy to your topic.
Clean Up
If you are creating this SNS topic and access policy for learning purpose, don’t forget to delete your CloudFormation stack, so that your topic is deleted and you don’t bear any cost.
Happy Learning !!!
Conclusion:
In this post, we learnt how to create amazon SNS topic policy using CloudFormation.
- We started with figuring out correct set of permission.
- Then we prepared policy for our usecase
- After that, we crafted the CloudFormation Template
- We created the stack and verified the applied policy in SNS console.
I hope you found this post helpful.
Enjoyed the content?
Subscribe to our newsletter below to get awesome AWS learning materials delivered straight to your inbox.
Don’t forget to motivate me by-
- Adding a comment below on what you liked and what can be improved.
- Follow us on
- Share this post with your friends
2 thoughts on “How to Create AWS SNS Topic Policy using CloudFormation”
This was awesome.. I can’t believe how poor the AWS docs describe this
Thank you Jonas – Glad it was helpful 🙂