user427875
user427875

Reputation: 1265

SNS topic not publishing to SQS

I am trying to prototype a distributed application using SNS and SQS.I have this topic:

arn:aws:sns:us-east-1:574008783416:us-east-1-live-auction

and this queue:

arn:aws:sqs:us-east-1:574008783416:queue4

I created the queue using the JS Scratchpad. I added the subscription using the Console. I AddPermission to the queue using the scratchpad. The queue policy is now:

{  
   "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"
      }
   ]
}

I have an email subscription on the same topic and the emails arrive fine but the messages never arrive on the queue. I've tried SendMessage directly to the queue - rather than via SNS - using Scratchpad and it works fine. Any ideas why it won't send to the queue?

Upvotes: 60

Views: 51359

Answers (11)

Rengas
Rengas

Reputation: 733

If you have raw message delivery enabled on SQS subscribers, then AWS has a hard restriction has 10 message attributes per message. I quote this from docs. This was the issue in my case.

Each message can have up to 10 attributes. Message attributes are optional and separate from the message body (however, they are sent alongside it)

.

Source

Upvotes: 0

Angel Reyes
Angel Reyes

Reputation: 41

It's by AWS::SQS::QueuePolicy.

You need define a this kind of policy to allow specific SNS perform actions to specific 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-*

With Lambda this kind of policies dont apply. Please if anyone know why please share it.

Upvotes: 1

Florin D
Florin D

Reputation: 1840

I just experienced this and took me a while to figure out why:

If I create a SQS subscription from the SNS console, it does not add necessary permissions to the SQS access policy.

If I create the subscription in the SQS console to the same SNS, it does.

Upvotes: 17

horizon7
horizon7

Reputation: 1293

If you have enabled encryption on your queue, can also be a reason for SNS not being able to put message on subscriber queue. You need to give access to SNS to that KMS key.

This article explains how to solve this problem:

Upvotes: 3

Ulad Kasach
Ulad Kasach

Reputation: 12808

Like the other answers mentioned, you must opt in and grant permission to this SNS topic to publish to your SQS queue.

If you use terraform, you can use the sqs_queue_policy resource.

Here is 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
}

Upvotes: 6

jackotonye
jackotonye

Reputation: 3853

Old question but using an AWS SDK version > 1.10

Check out the docs 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(new Principal("Service", "sns.amazonaws.com"))
           .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);
}

Which outputs a policy similar to

{
   Policy={
      "Version":"2012-10-17",
       "Id":"MainQueuePolicy",
       "Statement":
            [
              {
                 "Sid":"1",
                 "Effect":"Allow",
                 "Principal": {
                   "Service": "sns.amazonaws.com"
                 },
                 "Action":["sqs:SendMessage"],
                 "Condition":
                   {"ArnEquals":
                     {"aws:SourceArn":["arn:aws:sns:us-east-1:3232:testSubscription"]}
                   }
              }
            ]
      }
 }

Upvotes: 4

kichik
kichik

Reputation: 34704

Here's a full CloudFormation example of Skyler's answer

{
  "Resources": {
    "MyTopic": {
      "Type": "AWS::SNS::Topic"
    },
    "MyQueue": {
      "Type": "AWS::SQS::Queue"
    },
    "Subscription": {
      "Type" : "AWS::SNS::Subscription",
      "Properties" : {
          "Protocol" : "sqs",
          "TopicArn" : {"Ref": "MyTopic"},
          "Endpoint": {"Fn::GetAtt": ["MyQueue", "Arn"]}
        }
    },
    "QueuePolicy": {
      "Type": "AWS::SQS::QueuePolicy",
      "Properties": {
        "Queues": [
          {"Ref": "MyQueue"}
        ],
        "PolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Sid": "allow-sns-messages",
              "Effect": "Allow",
              "Principal": {"Service": "sns.amazonaws.com"},
              "Action": "sqs:SendMessage",
              "Resource": {"Fn::GetAtt": ["MyQueue", "Arn"]},
              "Condition": {
                "ArnEquals": {
                  "aws:SourceArn": {"Ref": "MyTopic"}
                }
              }
            }
          ]
        }
      }
    }
  }
}

Amazon has more options in their Sending Amazon SNS Messages to Amazon SQS Queues document.

Upvotes: 18

Shoter
Shoter

Reputation: 1039

Most of the answers (beside @spg answer) propose usage of principal: * - this is very dangerous practice and it will expose your SQS to whole world.

From AWS docs

For resource-based policies, such as Amazon S3 bucket policies, a wildcard (*) in the principal element specifies all users or public access.
We strongly recommend that you do not use a wildcard in the Principal element in a role's trust policy unless you otherwise restrict access through a Condition element in the policy. Otherwise, any IAM user in any account in your partition can access the role.

Therefore it is strongly not recommended to use this principal.

Instead you need to specify sns service as your principal:

"Principal": {
        "Service": "sns.amazonaws.com"
},

Example policy:

{
  "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"
    }
  ]
}

With this policy sns will be able to send messages to your SQSs.

There are more permissions for SQS but from what I see SendMessage and SendMessageBatch should be enough for SNS->SQS subscribtion.

Upvotes: 25

Natanael Rocha
Natanael Rocha

Reputation: 19

only you need subscribe the queue to the topic from the queue console.

  • step one: select the queue
  • step two: queue Actions
  • step three: Subscribe Queue to SNS Topic
  • step choose: the topic
  • end.

Upvotes: 1

spg
spg

Reputation: 9827

Adding to Skyler's answer, if like me you cringe at the idea of allowing any principal (Principal: '*'), you can restrict the principal to SNS:

Principal:
  Service: sns.amazonaws.com

Although this behavior is undocumented, it works.

Upvotes: 30

Skyler Johnson
Skyler Johnson

Reputation: 3873

This was posted a while back on the AWS forums: https://forums.aws.amazon.com/thread.jspa?messageID=202798

Then I gave the SNS topic the permission to send messages to the SQS queue. The trick here is to allow all principals. SNS doesn't send from your account ID -- it has its own account ID that it sends from.

Upvotes: 41

Related Questions