Amazon web services 从Cloudformation设置QueuePolicy不会在堆栈创建时生效,但在创建后设置相同的策略会生效

Amazon web services 从Cloudformation设置QueuePolicy不会在堆栈创建时生效,但在创建后设置相同的策略会生效,amazon-web-services,permissions,amazon-cloudformation,amazon-sqs,amazon-sns,Amazon Web Services,Permissions,Amazon Cloudformation,Amazon Sqs,Amazon Sns,我正在尝试从(现有)SNS主题创建一个队列和对它的订阅。同一帐户中的所有资源。我知道,为了做到这一点,队列需要有一个队列策略,允许SNS向队列发送消息 但是,我发现我通过Cloudformation创建的QueuePolicy似乎没有得到尊重—消息没有传递到队列,主题中的Cloudwatch日志报告传递失败,因为权限被拒绝。但是,如果我在创建后重新应用相同的策略,它将生效并传递消息 以下是我首先尝试的: $ cat template.yaml --- AWSTemplateFormatVersi

我正在尝试从(现有)SNS主题创建一个队列和对它的订阅。同一帐户中的所有资源。我知道,为了做到这一点,队列需要有一个队列策略,允许SNS向队列发送消息

但是,我发现我通过Cloudformation创建的QueuePolicy似乎没有得到尊重—消息没有传递到队列,主题中的Cloudwatch日志报告传递失败,因为权限被拒绝。但是,如果我在创建后重新应用相同的策略,它将生效并传递消息

以下是我首先尝试的:

$ cat template.yaml
---
AWSTemplateFormatVersion: "2010-09-09"

Description:
  ...

Parameters:
  TopicParameter:
    Type: String

Resources:
  Queue:
    Type: AWS::SQS::Queue

  Subscription:
    Type: AWS::SNS::Subscription
    DependsOn: QueuePolicy
    Properties:
      Endpoint:
        Fn::GetAtt:
          - "Queue"
          - "Arn"
      Protocol: "sqs"
      RawMessageDelivery: "true"
      TopicArn: !Ref TopicParameter

  QueuePolicy:
    Type: AWS::SQS::QueuePolicy
    Properties:
      PolicyDocument:
        Version: 2012-10-17
        Statement:
          - Sid: '1'
            Effect: Allow
            Principal: "*"
            Action: "SQS:SendMessage"
            Resource: !Ref Queue
            Condition:
              ArnEquals:
                aws:SourceArn: !Ref TopicParameter
      Queues:
        - !Ref Queue

Outputs:
  QueueArn:
    Value:
      Fn::GetAtt:
        - "Queue"
        - "Arn"
    Export:
      Name: "QueueArn"
$ aws cloudformation create-stack --stack-name my-test-stack --template-body file://template.yaml --parameters ParameterKey=TopicParameter,ParameterValue=<topicArn>
{
    "StackId": "<stackId>"
}
# ...wait...
$ aws cloudformation describe-stacks --stack-name my-test-stack --query "Stacks[0] | Outputs[0] | OutputValue"
"<queueArn>"
# Do some trivial substitution to get the QueueUrl - it's *probably* possible via the CLI, but I don't think you need me to prove that I can do it
$ aws sqs get-queue-attributes --queue-url <queueUrl> --attribute-names ApproximateNumberOfMessages --query "Attributes.ApproximateNumberOfMessages"
"0"
# The above is consistently true, even if I wait and retry after several minutes. I've confirmed that messages *are* being published from the topic via other subscriptions
$ aws sqs get-queue-attributes --queue-url <queueUrl> --attribute-names Policy --query "Attributes.Policy"
"{\"Version\":\"2012-10-17\",\"Statement\":[{\"Sid\":\"1\",\"Effect\":\"Allow\",\"Principal\":\"*\",\"Action\":\"SQS:SendMessage\",\"Resource\":\"<queueUrl>\",\"Condition\":{\"ArnEquals\":{\"aws:SourceArn\":\"<topicArn>\"}}}]}"
$ aws sqs get-queue-attributes --queue-url <queueUrl> --attribute-names Policy --query "Attributes.Policy" | | perl -pe 's/^.(.*?).$/$1/' | perl -pe 's/\\"/"/g' | python -m json.tool
{
    "Statement": [
        {
            "Action": "SQS:SendMessage",
            "Condition": {
                "ArnEquals": {
                    "aws:SourceArn": "<topicArn>"
                }
            },
            "Effect": "Allow",
            "Principal": "*",
            "Resource": "<queueUrl>",
            "Sid": "1"
        }
    ],
    "Version": "2012-10-17"
}
$cat template.yaml
---
AWST模板格式版本:“2010-09-09”
说明:
...
参数:
主题参数:
类型:字符串
资源:
队列:
类型:AWS::SQS::队列
订阅:
类型:AWS::SNS::订阅
DependsOn:QueuePolicy
特性:
终点:
Fn::GetAtt:
-“队列”
-“阿恩”
协议:“sqs”
RawMessageDelivery:“true”
托皮卡恩:!Ref主题参数
排队策略:
类型:AWS::SQS::QueuePolicy
特性:
政策文件:
版本:2012-10-17
声明:
-希德:“1”
效果:允许
校长:“*”
操作:“SQS:SendMessage”
资源:!参考队列
条件:
ArnEquals:
aws:SourceArn:!Ref主题参数
队列:
- !参考队列
产出:
QueueArn:
价值:
Fn::GetAtt:
-“队列”
-“阿恩”
出口:
名称:“QueueArn”
$aws cloudformation创建堆栈--堆栈名称我的测试堆栈--模板正文file://template.yaml --parameters ParameterKey=TopicParameter,ParameterValue=
{
“StackId”:”
}
#……等等。。。
$aws cloudformation描述堆栈--堆栈名称我的测试堆栈--查询“堆栈[0]|输出[0]|输出值”
""
#做一些简单的替换来获取QueueUrl—通过CLI*可能*是可能的,但我认为您不需要我来证明我可以做到这一点
$aws sqs获取队列属性--队列url--属性名称ApproximateEnumberOfMessages--查询“attributes.ApproximateEnumberOfMessages”
"0"
#即使我在几分钟后等待并重试,上述情况仍然是正确的。我已确认正在通过其他订阅从主题发布消息*
$aws sqs获取队列属性--队列url--属性名称策略--查询“attributes.Policy”
“{\'Version\':\'2012-10-17\',\'Statement\':[{\'Sid\':\'1\',\'Effect\':\'Allow\',\'Principal\':\'*\,\'Action\':\'SQS:SendMessage\',\'Resource\':\',\'Condition\':{\'arn equals\':{\'aws:SourceArn\':\':'
$aws sqs get队列属性--队列url--属性名称策略--查询“attributes.Policy”| | perl-pe's/^。(.*?)$/$1/'| perl-pe's/\\“/”/g'| python-m json.tool
{
“声明”:[
{
“操作”:“SQS:SendMessage”,
“条件”:{
“ArnEquals”:{
“aws:SourceArn”:”
}
},
“效果”:“允许”,
“委托人”:“*”,
“资源”:“,
“Sid”:“1”
}
],
“版本”:“2012-10-17”
}
在这一点上,一切看起来都是正确的。如果转到AWS控制台,我会看到队列上的QueuePolicy正是我所期望的,但没有消息

但是,如果我重新应用队列策略

$ aws sqs get-queue-attributes --queue-url <queueUrl> --attribute-names Policy --query "Attributes" > policyInFile
$ cat policyInFile
{
    "Policy": "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Sid\":\"1\",\"Effect\":\"Allow\",\"Principal\":\"*\",\"Action\":\"SQS:SendMessage\",\"Resource\":\"<queueUrl>\",\"Condition\":{\"ArnEquals\":{\"aws:SourceArn\":\"<topicArn>\"}}}]}"
}
$ aws sqs set-queue-attributes --queue-url <queueUrl> --attributes policyInFile
$aws sqs获取队列属性--队列url--属性名称策略--查询“属性”>policyInFile
$catpolicyinfile
{
“策略”:“{”版本\“:\”2012-10-17\“,\”语句\“:[{”Sid \“:\”1\“,\”效果\“:\”允许\“,”主体\“:\”*\”,”动作\“:”SQS:SendMessage\“,”资源\“:\”,”条件\“:{”ArnEquals \“:{”aws:SourceArn \“:\”:“\”,“\”,“}}”
}
$aws sqs设置队列属性--队列url--属性policyInFile
然后,几秒钟后,队列开始接收消息

更奇怪的是,我可以通过以下方式重现同样的行为:

  • 设置堆栈
  • 转到控制台中的队列
  • 确认队列未接收消息
  • 点击队列策略上的“编辑”
  • 点击“保存”(即-不更改策略中的任何内容)
  • 观察接收消息的队列

如何使Cloudformation堆栈中的QueuePolicy在创建队列时生效?

问题是我应该将队列的ARN用于
资源,而不是URL。我猜,当为队列设置QueuePolicy(通过控制台或CLI,但不是通过Cloudformation)时,
资源
字段被覆盖到相关队列的ARN。

问题是我应该将队列的ARN用于
资源
,而不是URL。我猜,当为队列设置QueuePolicy(通过控制台或CLI,但不是通过Cloudformation)时,
resource
字段被覆盖到相关队列的ARN。

我认为我应该在QueuePolicy中使用
资源的URL(我刚刚通过区分“before”和“after”找到了该URL),而不是ARN。现在确认……我想我应该在QueuePolicy中使用
资源的URL(我刚刚通过区分“before”和“after”找到),而不是ARN。现在确认。。。