CloudFormation is an AWS service that allows you to design your entire infrastructure in a text file (JSON or YAML). This file will be your only source of truth for your infrastructure. This service helps you to standardise your infrastructure components across your organisation.
SNS – Simple Notification Service is a messaging service that provides a low-cost infrastructure for sending large amount of messages. SNS is suitable for event notification, monitoring applications, workflow systems, time-sensitive information updates, mobile applications, and any other application that generates or consumes notifications.
SQS – Simple Queue Service is a message queuing service used for exchanging data between applications. It requires no upfront cost, no need to acquire, install, and configure messaging software, and no time-consuming build-out and maintenance of supporting infrastructure.
As I designed in the diagram, the second account will have:
- a SNS (AWS::SNS::Topic)
- a SQS (AWS::SQS::Queue) that is subscribed by the SNS
- a policy (AWS::SQS::QueuePolicy) that tells that the queue will receive messages only from that specific SNS.
- a policy for the SNS (AWS::SNS::TopicPolicy) which defines that a specific role can do a certain action (sns:Publish) to a specific SNS.
CloudFormation Parameters – Account 2
[
{
"ParameterKey": "ComponentName",
"ParameterValue": "MyAwesomeApp"
},
{
"ParameterKey": "Environment",
"ParameterValue": "int"
},
{
"ParameterKey": "HostAccountID",
"ParameterValue": "xxxxxxxxxxxxx"
},
{
"ParameterKey": "SubscriberAccountID",
"ParameterValue": "xxxxxxxxxxxxx"
},
{
"ParameterKey": "SubscriberRole",
"ParameterValue": "subscriber-role"
}
]
CloudFormation Template – Account 2
{
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "Queue for Storing Messages.",
"Parameters": {
"ComponentName": {
"Description": "Service component name.",
"Type": "String"
},
"Environment": {
"Description": "The name of the environment. int, test or live",
"Type": "String"
},
"HostAccountID": {
"Description": "The account ID that will host the input queue - current account",
"Type": "String"
},
"SubscriberAccountID": {
"Description": "The account ID that will subscribe to the input queue - cross account",
"Type": "String"
},
"SubscriberRole": {
"Description": "The role name of the subscriber to the queue",
"Type": "String"
}
},
"Resources": {
"MessagesQueue": {
"Type": "AWS::SQS::Queue",
"Properties": {
"QueueName": {
"Fn::Sub": "${Environment}-${ComponentName}-queue"
}
}
},
"MessagesNotificationTopic": {
"Type": "AWS::SNS::Topic",
"Properties": {
"Subscription" : [
{ "Endpoint" : { "Fn::GetAtt" : [ "MessagesQueue", "Arn" ] }, "Protocol" : "sqs" }
],
"TopicName": {
"Fn::Sub": "${Environment}-${ComponentName}-sns"
}
}
},
"MessagesNotificationTopicPolicy": {
"Type": "AWS::SNS::TopicPolicy",
"Properties": {
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": {
"Fn::Sub": "arn:aws:iam::${SubscriberAccountID}:role/${SubscriberRole}"
}
},
"Action": [
"sns:Publish"
],
"Resource": {
"Fn::Sub": "arn:aws:sns:eu-west-1:${HostAccountID}:${Environment}-${ComponentName}-sns"
}
}
]
},
"Topics": [
{
"Ref": "MessagesNotificationTopic"
}
]
}
},
"SQSPolicy": {
"Type" : "AWS::SQS::QueuePolicy",
"Properties" : {
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "SQS:SendMessage",
"Resource": {
"Fn::Sub": "arn:aws:sqs:eu-west-1:${HostAccountID}:${Environment}-${ComponentName}-queue"
},
"Condition": {
"ArnEquals": {
"aws:SourceArn": {
"Fn::Sub": "arn:aws:sns:eu-west-1:${HostAccountID}:${Environment}-${ComponentName}-sns"
}
}
}
}
]
},
"Queues": [
{ "Ref": "MessagesQueue" }
]
}
}
}
}
After we created all the resources in the second account, in the first account we only need to add:
- an IAM Managed Policy (AWS::IAM::ManagedPolicy) which dictates that a certain action (sns:Publish) can be made to a specific resource (SNS) with the effect allow.
CloudFormation Parameters – Account 1
[
{
"ParameterKey": "ComponentName",
"ParameterValue": "MyAwesomeApp"
},
{
"ParameterKey": "Environment",
"ParameterValue": "int"
},
{
"ParameterKey": "ToSubscribeAccountID",
"ParameterValue": "xxxxxxxxxxxxx"
}
]
CloudFormation Template – Account 1
{
"AWSTemplateFormatVersion":"2010-09-09",
"Description":"Provides rules for a Kubernetes cluster to interact with other AWS resources",
"Parameters": {
"ComponentName": {
"Description": "Service component name.",
"Type": "String"
},
"Environment": {
"Type": "String",
"Description": "The name of the environment. int, test or live"
}
"ToSubscribeAccountID": {
"Description": "The account ID where to subscribe - cross account",
"Type": "String"
}
},
"Resources":{
"PublishOnlyToSNS":{
"Type":"AWS::IAM::ManagedPolicy",
"Properties":{
"Description":"Provides access to Elastic Kubernetes Service resources",
"ManagedPolicyName": {
"Fn::Sub": "${Environment}-eks-resource-access"
},
"PolicyDocument":{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"sns:Publish"
],
"Resource": [
{ "Fn::Sub": "arn:aws:sns:eu-west-1:${ToSubscribeAccountID}:${Environment}-${ComponentName}-sns" }
],
"Effect": "Allow"
}
]
}
}
}
}
}
Leave a Reply