我正在尝试使用SNS和SQS对分布式应用程序进行原型设计。我有这个主题:
arn:aws:sns:us-east-1:574008783416:us-east-1-live-auction
和这个队列:
arn:aws:sqs:us-east-1:574008783416:queue4
我使用JS Scratchpad创建了队列。我使用控制台添加了订阅。我使用暂存器将AddPermission添加到队列中。队列策略现在是:
{
"Version":"2008-10-17",
"Id":"arn:aws:sqs:us-east-1:574008783416:queue4/SQSDefaultPolicy",
"Statement":[
{
"Sid":"RootPerms",
"Effect":"Allow",
"Principal":{
"AWS":"574008783416"
},
"Action":"SQS:*",
"Resource":"arn:aws:sqs:us-east-1:574008783416:queue4"
}
]
}
我有一个关于同一主题的电子邮件订阅,电子邮件很好地到达,但邮件从未到达队列。我已经尝试使用Scratchpad将SendMessage直接发送到队列 - 而不是通过SNS - 它工作正常。任何想法为什么它不会发送到队列?
答案 0 :(得分:13)
这篇文章在AWS论坛上发布了一段时间:https://forums.aws.amazon.com/thread.jspa?messageID=202798
然后我向SNS主题授予了向SQS队列发送消息的权限。这里的诀窍是允许所有校长。 SNS不会从您的帐户ID发送 - 它有自己的帐户ID。
答案 1 :(得分:4)
以下是Skyler回答的完整CloudFormation示例
"MyQueue": {
"Type": "AWS::SQS::Queue"
},
"QueuePolicy": {
"Type": "AWS::SQS::QueuePolicy",
"Properties": {
"Queues": [
{
"Ref": "MyQueue"
}
],
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Sid": "allow-sns-messages",
"Effect": "Allow",
"Principal": "*",
"Action": "sqs:SendMessage",
"Condition": {
"ArnEquals": {
"aws:SourceArn": {
"Ref": "MyTopic"
}
}
}
}
]
}
}
}
亚马逊在Sending Amazon SNS Messages to Amazon SQS Queues文档中有更多选项。
答案 2 :(得分:3)
旧问题,但使用的是AWS SDK版本> 1.10
查看文档SQS-SNS sendMessage Permission
private static void updateQueuePolicy(AmazonSQS sqs, String queueURL, String topicARN) {
Map<String, String> attributes = new HashMap<String, String>(1);
Action actions = new Action() {
@Override
public String getActionName() {
return "sqs:SendMessage"; // Action name
}
};
Statement mainQueueStatements = new Statement(Statement.Effect.Allow)
.withActions(actions)
.withPrincipals(Principal.All)
.withConditions(
new Condition()
.withType("ArnEquals")
.withConditionKey("aws:SourceArn")
.withValues(topicARN)
);
final Policy mainQueuePolicy = new Policy()
.withId("MainQueuePolicy")
.withStatements(mainQueueStatements);
attributes.put("Policy", mainQueuePolicy.toJson());
updateQueueAttributes(sqs, queueURL, attributes);
}
哪个输出类似于
{
Policy={
"Version":"2012-10-17",
"Id":"MainQueuePolicy",
"Statement":
[
{"Sid":"1",
"Effect":"Allow",
"Principal":"*",
"Action":["sqs:SendMessage"],
"Condition":
{"ArnEquals":
{"aws:SourceArn":["arn:aws:sns:us-east-1:3232:testSubscription"]}
}
}]
}
}
答案 3 :(得分:2)
大多数答案(在@spg答案旁边)都建议使用principal: *
-这是非常危险的做法,会将您的SQS暴露给全世界。
来自AWS docs
对于基于资源的策略(例如Amazon S3存储桶策略),principal元素中的通配符(*)指定所有用户或公共访问权限。
强烈建议您不要在角色的信任策略的Principal元素中使用通配符,除非您通过策略中的Condition元素限制访问。否则,您分区中任何帐户中的任何IAM用户都可以访问该角色。
因此,强烈建议不要使用此主体。
相反,您需要将sns服务指定为主体:
"Principal": {
"Service": "sns.amazonaws.com"
},
政策示例:
{
"Version": "2012-10-17",
"Id": "Policy1596186813341",
"Statement": [
{
"Sid": "Stmt1596186812579",
"Effect": "Allow",
"Principal": {
"Service": "sns.amazonaws.com"
},
"Action": [
"sqs:SendMessage",
"sqs:SendMessageBatch"
],
"Resource": "Your-SQS-Arn"
}
]
}
使用此策略,sns将能够向您的SQS发送消息。
SQS有more permissions,但从我看来SendMessage
和SendMessageBatch
足以满足SNS-> SQS的要求。
答案 4 :(得分:1)
添加到Skyler的答案中,如果像我一样对允许任何主体(Principal: '*'
)的想法感到畏缩,则可以将主体限制为SNS:
Principal:
Service: sns.amazonaws.com
尽管这种行为没有记录,但可以。
答案 5 :(得分:1)
仅需要从队列控制台将队列订阅到主题。
答案 6 :(得分:0)
与提到的其他答案一样,您必须选择加入并授予此 SNS 主题的权限才能发布到您的 SQS 队列。
如果您使用 terraform,则可以使用 sqs_queue_policy 资源。
这是an example:
resource "aws_sqs_queue_policy" "your_queue_policy" {
queue_url = "${aws_sqs_queue.your_queue.id}"
policy = <<POLICY
{
"Version": "2012-10-17",
"Id": "sqspolicy",
"Statement": [
{
"Sid": "First",
"Effect": "Allow",
"Principal": "*",
"Action": "sqs:SendMessage",
"Resource": "${aws_sqs_queue.your_queue.arn}",
"Condition": {
"ArnEquals": {
"aws:SourceArn": "${aws_sns_topic.your_topic.arn}"
}
}
}
]
}
POLICY
}
答案 7 :(得分:0)
如果您在队列上启用了加密,也可能是 SNS 无法将消息放入订阅者队列的原因。您需要授予该 KMS 密钥访问 SNS 的权限。
Redis Enterprise Cloud hosted in Azure 解释了如何解决这个问题: