如何在我的 Amazon SQS 队列和 AWS CloudFormation 中的 Amazon SNS 主题之间创建订阅?
上次更新时间:2019 年 10 月 2 日
如何在我的 Amazon Simple Queue Service (Amazon SQS) 队列和 AWS CloudFormation 中的 Amazon Simple Notification Service (Amazon SNS) 主题之间创建订阅?
解决方法
请根据您的使用案例从下列解决方案中选择一种:
- 如果 SNS 主题和 SQS 队列位于同一堆栈中, 请利用 AWS CloudFormation 模板创建向 Amazon SQS 队列发送消息的主题。
- 如果 SNS 主题和将会订阅该 SNS 主题的 SQS 队列位于同一 AWS 区域的不同堆栈中,请创建跨堆栈引用。
注意:当您创建跨堆栈参考时,将 SQS 队列的 Amazon 资源名称 (ARN) 导出到一个堆栈中。然后,将 SNS 主题的订阅终端节点属性中的 SQS 队列 ARN 导入另一个堆栈中。 - 如果 SNS 主题和 SQS 队列位于不同的 AWS 区域,请按照使用 AWS::SNS::Subscription 资源来设置跨区域订阅部分描述的步骤进行操作。
- 如果 SNS 主题和 SQS 队列位于不同的 AWS 账户,请按照使用 AWS::SNS::Subscription 资源来设置跨账户订阅部分描述的步骤进行操作。
使用 AWS::SNS::Subscription 资源来设置跨区域订阅
1. 在位于一个 AWS 区域的堆栈的 AWS CloudFormation 模板中声明该区域的 SNS 主题,然后创建一个输出资源来注释 SNS 主题 ARN。
请参阅以下 JSON 和 YAML 示例模板。
JSON:
{
"Resources": {
"SnsTopic": {
"Type": "AWS::SNS::Topic"
}
},
"Outputs": {
"SnsTopicArn": {
"Value": "SnsTopic"
}
}
}
YAML:
Resources:
SnsTopic:
Type: AWS::SNS::Topic
Outputs:
SnsTopicArn:
Value: !Ref SnsTopic
2. 在位于另一个 AWS 区域的另一个堆栈的 AWS CloudFormation 模板中,定义 AWS::SNS::Subscription 资源和 SQS 队列。
注意:将 awsSNSTopicArnExample 替换为您的 SNS 主题 ARN,并将 us-east-1 替换为您的 AWS 区域。
请参阅以下 JSON 和 YAML 示例模板。
JSON:
{
"Parameters": {
"SNSTopicARN": {
"Type": "String",
"Description": "awsSNSTopicArnExample"
},
"TopicRegion": {
"Type": "String",
"Description": "us-east-1"
}
},
"Resources": {
"Queue": {
"Type": "AWS::SQS::Queue"
},
"SnsSubscription": {
"Type": "AWS::SNS::Subscription",
"Properties": {
"Protocol": "sqs",
"Endpoint": {
"Fn::GetAtt": [
"Queue",
"Arn"
]
},
"Region": {
"Ref": "TopicRegion"
},
"TopicArn": {
"Ref": "SNSTopicARN"
}
}
}
}
}
YAML:
Parameters:
SNSTopicARN:
Type: String
Description: awsSNSTopicArnExample
TopicRegion:
Type: String
Description: us-east-1
Resources:
Queue:
Type: AWS::SQS::Queue
SnsSubscription:
Type: AWS::SNS::Subscription
Properties:
Protocol: sqs
Endpoint: !GetAtt Queue.Arn
Region: !Ref TopicRegion
TopicArn: !Ref SNSTopicARN
您的跨区域订阅现已设置。
使用 AWS::SNS::Subscription 资源设置跨账户订阅
1. 在位于一个 AWS 源账户的堆栈的 AWS CloudFormation 模板中,声明 SNS 主题和 AWS::SNS::TopicPolicy。然后,创建一个输出资源来注释 SNS 主题 ARN,并提供您的目标 AWS 账户作为参数。
请参阅以下 JSON 和 YAML 示例模板。
JSON:
{
"Parameters": {
"CrossAccountNumber": {
"AllowedPattern": "[0-9]+",
"Description": "The 12 digit AWS account number to grant access to.",
"MaxLength": "12",
"MinLength": "12",
"Type": "String",
"Default": 123456789101
}
},
"Resources": {
"SnsTopic": {
"Type": "AWS::SNS::Topic"
},
"SnsTopicPolicy": {
"Type": "AWS::SNS::TopicPolicy",
"DependsOn": "SnsTopic",
"Properties": {
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Sid": "SnsTopicPolicy",
"Effect": "Allow",
"Principal": {
"AWS": {
"Fn::Sub": "arn:aws:iam::${CrossAccountNumber}:root"
}
},
"Action": [
"sns:Subscribe"
],
"Resource": {
"Ref": "SnsTopic"
}
}
]
},
"Topics": [
{
"Ref": "SnsTopic"
}
]
}
}
},
"Outputs": {
"SnsTopicArn": {
"Value": {
"Ref": "SnsTopic"
}
}
}
}
YAML:
Parameters:
CrossAccountNumber:
AllowedPattern: '[0-9]+'
Description: The 12 digit AWS account number to grant access to.
MaxLength: '12'
MinLength: '12'
Type: String
Default: 123456789101
Resources:
SnsTopic:
Type: AWS::SNS::Topic
SnsTopicPolicy:
Type: AWS::SNS::TopicPolicy
DependsOn: SnsTopic
Properties:
PolicyDocument:
Version: '2012-10-17'
Statement:
- Sid: SnsTopicPolicy
Effect: Allow
Principal:
AWS: !Sub arn:aws:iam::${CrossAccountNumber}:root
Action:
- sns:Subscribe
Resource: !Ref SnsTopic
Topics:
- !Ref SnsTopic
Outputs:
SnsTopicArn:
Value: !Ref SnsTopic
2. 在位于您想要扩展订阅所在的 AWS 账户的堆栈的 AWS CloudFormation 模板中,定义 AWS::SNS::Subscription 资源、SQS 队列和 AWS::SQS::QueuePolicy 策略。
注意:将 awsSNSTopicArn 替换为您的 SNS 主题 ARN,并将 us-east-1 替换为您的 AWS 区域。
请参阅以下 JSON 和 YAML 示例模板。
JSON:
{
"Parameters": {
"SNSTopicARN": {
"Type": "String",
"Default": "awsSNSTopicArn"
},
"TopicRegion": {
"Type": "String",
"Default": "us-east-1"
}
},
"Resources": {
"Queue": {
"Type": "AWS::SQS::Queue"
},
"SqsQueuePolicy": {
"Type": "AWS::SQS::QueuePolicy",
"Properties": {
"PolicyDocument": {
"Version": "2012-10-17",
"Id": "MyQueuePolicy",
"Statement": [
{
"Sid": "Allow-SNS-SendMessage",
"Effect": "Allow",
"Principal": "*",
"Action": [
"sqs:SendMessage"
],
"Resource": {
"Fn::GetAtt": [
"Queue",
"Arn"
]
},
"Condition": {
"ArnEquals": {
"aws:SourceArn": {
"Ref": "SNSTopicARN"
}
}
}
}
]
},
"Queues" : [
{
"Ref" : "Queue"
}
]
}
},
"SnsSubscription": {
"Type": "AWS::SNS::Subscription",
"Properties": {
"Protocol": "sqs",
"Endpoint": {
"Fn::GetAtt": [
"Queue",
"Arn"
]
},
"Region": {
"Ref": "TopicRegion"
},
"TopicArn": {
"Ref": "SNSTopicARN"
}
}
}
}
}
YAML:
Parameters:
SNSTopicARN:
Type: String
Default: awsSNSTopicArn
TopicRegion:
Type: String
Default: us-east-1
Resources:
Queue:
Type: AWS::SQS::Queue
SqsQueuePolicy:
Type: AWS::SQS::QueuePolicy
Properties:
PolicyDocument:
Version: '2012-10-17'
Id: MyQueuePolicy
Statement:
- Sid: Allow-SNS-SendMessage
Effect: Allow
Principal: "*"
Action:
- sqs:SendMessage
Resource: !GetAtt Queue.Arn
Condition:
ArnEquals:
aws:SourceArn: !Ref SNSTopicARN
Queues:
- !Ref Queue
SnsSubscription:
Type: AWS::SNS::Subscription
Properties:
Protocol: sqs
Endpoint: !GetAtt Queue.Arn
Region: !Ref TopicRegion
TopicArn: !Ref SNSTopicARN