1

I try to enable a SNS topic to send messages to given SQS queue using the .NET client:

var policy = new Policy()
{
    Statements = new List<Statement>() {
        new Statement(Statement.StatementEffect.Allow) {
            Principals = new List<Principal>() { Principal.AllUsers },
            Actions = new List<ActionIdentifier>() { SQSActionIdentifiers.SendMessage },
            Conditions = new List<Condition>
            {
                ConditionFactory.NewCondition(ConditionFactory.ArnComparisonType.ArnEquals, "aws:SourceArn", topicArn)
            }
        }
    }
};

var request = new SetQueueAttributesRequest()
{
    QueueUrl = queueUrl,
    Attributes = new Dictionary<string, string>
    {
        { QueueAttributeName.Policy, policy.ToJson()}
    }
};
sqs.SetQueueAttributes(request);

This generates a policy that does not work:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "<sid>",
      "Effect": "Allow",
      "Principal": {
        "AWS": "*"
      },
      "Action": "sqs:SendMessage",
      "Condition": {
        "ArnEquals": {
          "aws:SourceArn": "arn:aws:sns:us-west-2:<id>:testTopic2"
        }
      }
    }
  ]
}

However if I delete this policy and add it manually, it works, and it looks almost identical, with some differences:

{
  "Version": "2012-10-17",
  "Id": "arn:aws:sqs:us-west-2:<id>:testQueue2/SQSDefaultPolicy",
  "Statement": [
    {
      "Sid": "<sid2>",
      "Effect": "Allow",
      "Principal": "*",
      "Action": "SQS:SendMessage",
      "Resource": "arn:aws:sqs:us-west-2:<id>:testQueue2",
      "Condition": {
        "ArnEquals": {
          "aws:SourceArn": "arn:aws:sns:us-west-2:<id>:testTopic2"
        }
      }
    }
  ]
}

The programmatic one:

  • lacks Id.
  • says "Principal" : "{ AWS: "*"} rather than "Principal" : "*".

I have tried to set the Id and the principal to a custom one but I only get HTTP 400s.

Which would be the right way of giving a SNS topic permissions to send messages to a SQS queue using the .NET client?

Full example

vtortola
  • 34,709
  • 29
  • 161
  • 263

1 Answers1

3

The most important part lacking in the JSON generated by your code is

  "Resource": "arn:aws:sqs:us-west-2:<id>:testQueue2"

Without specifying Resource, IAM can't tell for which resource you are granting access.

Then you can add a Resource object like this:

  new Statement(Statement.StatementEffect.Allow) {
     Principals = new List<Principal>() { Principal.AllUsers },
     Resources = new List<Principal>() { new Resource("arn:aws:sqs:us-west-2:<id>:testQueue2") }
  ....

(I am not a C# pro so syntax may be wrong but you've got the idea.)

Cagatay Gurturk
  • 7,186
  • 3
  • 34
  • 44