无法以编程方式为SQS队列授予SNS主题权限

时间:2017-02-28 17:29:35

标签: .net amazon-web-services aws-sdk amazon-sqs amazon-sns

我尝试使用.NET客户端启用SNS主题将消息发送到给定的SQS队列:

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);

这会生成不起作用的策略:

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

但是,如果我删除此政策并手动添加,它会起作用,看起来几乎相同,但存在一些差异:

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

程序化的一个:

  • 缺少Id
  • "Principal" : "{ AWS: "*"}而不是"Principal" : "*"

我尝试将Id和主体设置为自定义但我只获得HTTP 400s。

使用.NET客户端提供SNS主题权限以将消息发送到SQS队列的正确方法是什么?

Full example

1 个答案:

答案 0 :(得分:3)

您的代码生成的JSON中最缺少的部分是

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

如果不指定资源,IAM无法判断您授予访问权限的资源。

然后你可以像这样添加一个Resource对象:

  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") }
  ....

(我不是C#pro,所以语法可能有问题,但你已经有了这个想法。)