Настройка политики очередей из Cloudformation не вступает в силу при создании стека, но вступает в силу установка идентичной политики после создания

#amazon-web-services #permissions #amazon-cloudformation #amazon-sqs #amazon-sns

#amazon-web-services #разрешения #aws-cloudformation #amazon-sqs #amazon-sns

Вопрос:

Я пытаюсь создать очередь и подписку на нее из (существующего) раздела SNS. Все ресурсы в одной учетной записи. Я знаю, что для этого в очереди должна быть политика очередей, которая позволяет SNS SendMessage обращаться к очереди.

Однако я обнаружил, что политика очередей, которую я создал через 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, я вижу в очереди политику очередей, которая является именно тем, что я ожидаю, — но никаких сообщений.

Однако, если я повторно применю политику очередей…

 $ 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
  

Затем, через несколько секунд, очередь начинает получать сообщения.

Что еще более странно, я могу воспроизвести это же поведение, выполнив следующее:

  • настройте стек
  • переход к очереди в консоли
  • подтвердите, что очередь не получает сообщений
  • нажмите «Редактировать» в политике очереди
  • нажмите «Сохранить» (то есть — ничего не меняя в политике)
  • обратите внимание на очередь, принимающую сообщения

Как я могу заставить политику очередей в стеке Cloudformation вступить в силу во время создания очереди?

Комментарии:

1. Я думаю , что мне следовало использовать URL для resource в политике очередей (который я только что нашел, различая «до» и «после»), а не ARN. Подтверждения сейчас…

Ответ №1:

Проблема заключалась в том, что я должен был использовать ARN очереди для resource , а не URL. Я предполагаю, что при настройке политики очередей для очереди (через консоль или CLI, но не через Cloudformation) resource поле перезаписывается на ARN рассматриваемой очереди.