Можно ли применять фильтр SNS одновременно с подпиской?

Предположим, тема AWS SNS. Сообщения на эту тему имеют атрибут MessageAttribute "IsTestMessage" типа String.

Используя консоль AWS, я добавляю нового подписчика электронной почты. Они получают подтверждение по электронной почте. После подтверждения они получат все сообщения на эту тему, включая тестовые сообщения. Это не предназначено.

Я хотел бы применить фильтр до их подтверждения, позволяющий мне сказать IsTestMessage: "false" например.

Могу ли я применить фильтр во время создания подписки, чтобы избежать этих неправильных доставок? Похоже, в консоли нет способа сделать это, но я открыт для использования CLI, SDK и т. Д.

2 ответа

У вызова API подписки Amazon SNS есть поле с именем Attributes:

Присваивает атрибуты подписке как карту пар ключ-значение. Вы можете назначить любой атрибут, который поддерживается SetSubscriptionAttributes действие.

Вызов API SetSubscriptionAttributes может принять FilterPolicy согласно фильтрации сообщений с Amazon SNS.

Это должно соответствовать вашим требованиям.

Проходя CLI, я продолжал сталкиваться с той же ошибкой, что и @John Rotenstein: Error parsing parameter '--attributes': Expected: '=', received: '"'

Что бы я ни пробовал, он не брал, поэтому я могу только предположить, что часть sdk забита.

Полный пример bash создания темы SNS, очереди SQS и добавления подписки:

      # some params - SNS_ENDPOINT and SQS_ENDPOINT are for localstack - you probably don't need them
# in production
SQS_ENDPOINT="${SQS_ENDPOINT:-http://localhost:4566}"
SNS_ENDPOINT="${SNS_ENDPOINT:-http://localhost:4575}"
REGION=eu-west-1

# Create an SNS topic, "my-topic" and extract the ARN
MY_TOPIC_ARN=$(aws sns create-topic --name "my-topic" --endpoint-url=$SNS_ENDPOINT --region=$REGION --query TopicArn --output text)

# Create a SQS queue that will get messages from the SNS topic - extract the url
MY_QUEUE_URL=$(aws sqs create-queue --queue-name "my-queue" --endpoint-url=$SQS_ENDPOINT --region=$REGION --query QueueUrl --output text)

# Get the queue arn
MY_QUEUE_ARN=$(aws sqs get-queue-attributes --queue-url "$MY_QUEUE_URL" --endpoint-url=$SQS_ENDPOINT --attribute-names QueueArn --query Attributes --output text)

# Subscribe our sqs queue to our sns topic - extract the subscription arn
MY_SUBSCRIPTION_ARN=$(aws sns subscribe --topic-arn $MY_TOPIC_ARN --protocol sqs --notification-endpoint $MY_QUEUE_ARN --endpoint-url=$SNS_ENDPOINT --region=$REGION --attributes RawMessageDelivery=true --query SubscriptionArn --output text)

# Add a filter policy
aws sns set-subscription-attributes --subscription-arn $MY_SUBSCRIPTION_ARN --attribute-name FilterPolicy --attribute-value "{\"someKey\":[\"someValue\"]}" --endpoint-url=$SQS_ENDPOINT --region=$REGION

Примечание. Это не касается настройки очереди недоставленных сообщений (одна для самой подписки и одна для очереди SQS, в зависимости от того, что вы с ней делаете), а также политики, которую вам необходимо разрешить. SNS для отправки сообщений в SQS и т. д.

Облако

https://docs.aws.amazon.com/sns/latest/dg/SendMessageToSQS.cloudformation.html приводит пример создания темы с подпиской одновременно:

      "Resources": {
    "MySNSTopic": {
      "Type": "AWS::SNS::Topic",
      "Properties": {
        "Subscription": [{
            "Endpoint": {
              "Fn::GetAtt": ["MyQueue1", "Arn"]
            },
            "Protocol": "sqs"
          }]
      }
    },
    ...
}

Я не пробовал это, так что я не могу говорить о нем

Бессерверный

Вы также можете создать их отдельно через Serverless:

        Resources: 
    MyTopic:
      Type: "AWS::SNS::Topic"
      Properties:
        TopicName: ${self:custom.myTopicName}

    MyTopicQueue:
      Type: "AWS::SQS::Queue"
      Properties:
        QueueName: ${self:custom.myTopicQueueName}
        VisibilityTimeout: 120
        RedrivePolicy: 
          maxReceiveCount: 3
          deadLetterTargetArn:
            Fn::GetAtt: 
              - MyTopicQueueDeadLetter
              - Arn
    MyTopicQueueDeadLetter:
      Type: "AWS::SQS::Queue"
      Properties:
        QueueName: ${self:custom.myTopicDeadQueueName}

    # Policy to allow SNS to post to SQS
    MyTopicQueuePolicy:
      Type: AWS::SQS::QueuePolicy
      Properties:
        PolicyDocument:
          Version: "2012-10-17"
          Statement:
            Effect: "Allow"
            Principal:
              Service: sns.amazonaws.com
            Resource: 
              - !GetAtt
                - MyTopicQueue
                - Arn
              - !GetAtt
                - MyTopicQueueDeadLetter
                - Arn
            Action: 
              - sqs:*
            Condition:
              ArnEquals:
                aws:SourceArn: !Ref MyTopic
        Queues:
          - Ref: MyTopicQueue
          - Ref: MyTopicQueueDeadLetter

    # Create the subscription for the SNS to SQS queue
    MyTopicSnsToSqsSubscription:
      Type: "AWS::SNS::Subscription"
      Properties:
        TopicArn: !Ref MyTopic
        Endpoint: !GetAtt
          - MyTopicQueue
          - Arn
        Protocol: sqs
        RawMessageDelivery: 'true'
        FilterPolicy:
          type:
            - 'playerLost'
        RedrivePolicy:
          deadLetterTargetArn: !GetAtt
            - MyTopicQueueDeadLetter
            - Arn

Я все еще не уверен на 100% в политике, так как в консоли AWS, когда я смотрю на подписку, она все еще говорит, что у нее нет разрешения на публикацию в очередь недоставленных сообщений (здесь я использую одна и та же очередь недоставленных сообщений для подписки и основная очередь SQS), поэтому я явно что-то упускаю.

Подобно CloudFormation, вы, вероятно, можете объявить подписку напрямую при объявлении темы, но я этого не пробовал.

Должно быть достаточно, чтобы вы начали

Другие вопросы по тегам