Я пытаюсь создать очередь и подписку на нее из (существующей) темы SNS.Все ресурсы в одном аккаунте.Я знаю, что для этого в очереди должна быть QueuePolicy, которая позволяет SNS SendMessage
в очередь.
Однако я обнаружил, что QueuePolicy, созданный с помощью Cloudformation, делаеткажется, что не соблюдается - сообщения не доставляются в очередь, и 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"
}
На данный момент все выглядит правильно.Если я захожу в консоль AWS, я вижу в очереди QueuePolicy, что именно то, что я ожидаю, но без сообщений.
Если я повторно применю 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
Затем, через несколько секунд, очередь начинает получать сообщения.
Еще более странно, я могу воспроизвести такое же поведение, выполнив следующее:
- настроить стек
- , идущий в очередь в консоли
- подтвердить, что очередь не получает сообщения
- нажать «Изменить» в политике очереди
- нажать «Сохранить» (то есть - ничего не меняя в политике )
- наблюдать за очередью получения сообщений
Как сделать QueuePolicy встек Cloudformation вступает в силу во время создания очереди?