Можно ли применять фильтр 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, вы, вероятно, можете объявить подписку напрямую при объявлении темы, но я этого не пробовал.
Должно быть достаточно, чтобы вы начали