Тема SNS не публикуется в SQS
Я пытаюсь создать прототип распределенного приложения с использованием SNS и SQS. У меня есть эта тема:
arn:aws:sns:us-east-1:574008783416:us-east-1-live-auction
и эта очередь:
arn:aws:sqs:us-east-1:574008783416:queue4
Я создал очередь, используя JS Scratchpad. Я добавил подписку с помощью Консоли. Я добавляю разрешение в очередь, используя блокнот. Политика очереди теперь:
{
"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"
}
]
}
У меня есть подписка по электронной почте на ту же тему, и письма приходят нормально, но сообщения никогда не приходят в очередь. Я пробовал SendMessage непосредственно в очередь - а не через SNS - используя Scratchpad, и он работает нормально. Есть идеи, почему его не отправят в очередь?
10 ответов
Это было опубликовано некоторое время назад на форумах AWS: https://forums.aws.amazon.com/thread.jspa?messageID=202798
Затем я дал теме SNS разрешение отправлять сообщения в очередь SQS. Хитрость здесь в том, чтобы позволить всем принципалам. SNS не отправляет с вашего идентификатора учетной записи - он имеет свой собственный идентификатор учетной записи, с которого он отправляет.
Добавляя к ответу Скайлера, если вы, как и я, съеживаетесь от идеи разрешения какого-либо принципала (Principal: '*'
), вы можете ограничить принципала SNS:
Principal:
Service: sns.amazonaws.com
Хотя это поведение недокументировано, оно работает.
Большинство ответов (кроме ответа @spg) предлагают использование principal: *
- это очень опасная практика, и она раскроет ваш SQS для всего мира.
Для политик на основе ресурсов, таких как политики корзины Amazon S3, подстановочный знак (*) в основном элементе указывает всех пользователей или общий доступ.
Мы настоятельно рекомендуем вам не использовать подстановочный знак в элементе Principal в политике доверия роли, если вы не ограничиваете доступ другим способом с помощью элемента Condition в политике. В противном случае любой пользователь IAM в любой учетной записи в вашем разделе может получить доступ к роли.
Поэтому использовать этот принцип настоятельно не рекомендуется.
Вместо этого вам нужно указать sns service в качестве принципала:
"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 есть больше разрешений, но из того, что я вижуSendMessage
а также SendMessageBatch
должно хватить для подписки на SNS->SQS.
Вот полный 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"
}
}
}
}
]
}
}
}
У Amazon есть больше опций в документе Отправка сообщений Amazon SNS в очереди Amazon SQS.
Я только что испытал это, и мне потребовалось некоторое время, чтобы понять, почему:
Если я создаю подписку SQS из консоли SNS, она не добавляет необходимые разрешения в политику доступа SQS.
Если я создам подписку в консоли SQS на тот же SNS, это произойдет.
Как и в других упомянутых ответах, вы должны зарегистрироваться и предоставить разрешение этой теме SNS для публикации в вашей очереди SQS.
Если вы используете terraform, вы можете использовать ресурс sqs_queue_policy .
Вот пример :
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
}
Старый вопрос, но с использованием версии AWS SDK> 1.10
Проверьте документы SQS-SNS sendMessage Разрешение
private static void updateQueuePolicy(AmazonSQS sqs, String queueURL, String queueARN) {
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(queueARN)
);
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"]}
}
}]
}
}
Если вы включили шифрование в своей очереди, это также может быть причиной того, что SNS не может поместить сообщение в очередь подписчика. Вам необходимо предоставить доступ к SNS для этого ключа KMS.
В этой статье объясняется, как решить эту проблему:
Только вам нужно подписать очередь на тему из консоли очереди.
- шаг первый: выберите очередь
- шаг второй: действия в очереди
- шаг третий: очередь подписки на тему SNS
- шаг выбрать: тема
- конец.
Это AWS::SQS::QueuePolicy.
Вам необходимо определить политику такого типа, чтобы разрешить определенным SNS выполнять действия с определенными SQS.
QueuePolicy:
Type: AWS::SQS::QueuePolicy
Properties:
Queues:
- Ref: MyQueue1
- Fn::Sub: arn:aws:sqs:us-east-1:${AWS::AccountId}:my-queue-*
PolicyDocument:
Version: '2012-10-17'
Statement:
- Sid: allow-sns-messages
Effect: Allow
Principal:
Service: sns.amazonaws.com
Action: sqs:SendMessage
Resource:
- Fn::Sub: arn:aws:sqs:us-east-1:${AWS::AccountId}:my-queue-*
Condition:
ArnEquals:
aws:SourceArn:
- Fn::Sub: arn:aws:sns:us-east-1:${AWS::AccountId}:source-sns-*
С Lambda такие политики не применяются. Пожалуйста, если кто-нибудь знает, почему, пожалуйста, поделитесь им.