Amazon SNSのrawメッセージ配信設定の違いをCloudFormationで手軽に勉強する

2021.07.16

Amazon SNS(以降、SNS)のrawメッセージ配信を実際に使ったことがなかったので、有効/無効によってどのような違いが出るのか試してみました。

rawメッセージ配信とは

rawメッセージ配信を有効にすると、SNSから発行されたメッセージからAmazon SNSメタデータが削除され、生のメッセージが送信されます。

Amazon SNS の raw メッセージ配信 - Amazon Simple Notification Service

開発者ガイドに挙げられたサンプルによると、設定の有効/無効で、メッセージが以下のように変わります。

  • rawメッセージ配信が無効なとき
    {
      "Type": "Notification",
      "MessageId": "dc1e94d9-56c5-5e96-808d-cc7f68faa162",
      "TopicArn": "arn:aws:sns:us-east-2:111122223333:ExampleTopic1",
      "Subject": "TestSubject",
      "Message": "This is a test message.",
      "Timestamp": "2021-02-16T21:41:19.978Z",
      "SignatureVersion": "1",
      "Signature": "FMG5tlZhJNHLHUXvZgtZzlk24FzVa7oX0T4P03neeXw8ZEXZx6z35j2FOTuNYShn2h0bKNC/zLTnMyIxEzmi2X1shOBWsJHkrW2xkR58ABZF+4uWHEE73yDVR4SyYAikP9jstZzDRm+bcVs8+T0yaLiEGLrIIIL4esi1llhIkgErCuy5btPcWXBdio2fpCRD5x9oR6gmE/rd5O7lX1c1uvnv4r1Lkk4pqP2/iUfxFZva1xLSRvgyfm6D9hNklVyPfy+7TalMD0lzmJuOrExtnSIbZew3foxgx8GT+lbZkLd0ZdtdRJlIyPRP44eyq78sU0Eo/LsDr0Iak4ZDpg8dXg==",
      "SigningCertURL": "https://sns.us-east-2.amazonaws.com/SimpleNotificationService-010a507c1833636cd94bdb98bd93083a.pem",
      "UnsubscribeURL": "https://sns.us-east-2.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:us-east-2:111122223333:ExampleTopic1:e1039402-24e7-40a3-a0d4-797da162b297"
    }

  • rawメッセージ配信が有効なとき

    This is a test message.

私は、仕様は知っていはいたものの、なんだかんだ実際に使ったことがありませんでした。

今回はこの仕組みを実際に動かしてみて、送信されるメッセージがどのように変わるのか見てみたいと思います。

また、誰でも簡単に検証ができるよう、rawメッセージ配信が有効/無効な場合のそれぞれで、CloudFormation(以降、CFn)のテンプレートも作成しました。

作成した構成

SNSからSQSへメッセージを送信する構成を作成しました。

作成した構成

raw メッセージ配信の有効/無効で2つ構成を作り、比較します。

CFnテンプレート

CFnでは、raw メッセージ配信の有効/無効を、AWS::SNS::SubscriptionRawMessageDeliverプロパティの値を変えることで定義できます。

AWS::SNS::Subscription - AWS CloudFormation

raw メッセージ配信が無効

AWSTemplateFormatVersion: 2010-09-09
Description: SNS disabled raw message delivery and Queue

Resources:
  myTopic:
    Type: AWS::SNS::Topic
    Properties:
      TopicName: cm-nayuta-subscribe-test-topic
        
  Queue:
    Type: AWS::SQS::Queue
    Properties:
      QueueName: cm-nayuta-subscribe-test-queue
  QueuePolicy:
    Type: AWS::SQS::QueuePolicy
    Properties:
      Queues:
        - !Ref Queue
      PolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal: "*"
            Action:
              - sqs:SendMessage
            Resource: "*"
            Condition:
              ArnEquals:
                aws:SourceArn: !Ref myTopic
      
  SnsSubscription:
    Type: AWS::SNS::Subscription
    Properties:
      Protocol: sqs
      Endpoint: !GetAtt Queue.Arn
      TopicArn: !Ref myTopic
      RawMessageDelivery: 'false'

raw メッセージ配信が有効

AWSTemplateFormatVersion: 2010-09-09
Description: SNS enabled raw message delivery and Queue

Resources:
  myTopic:
    Type: AWS::SNS::Topic
    Properties:
      TopicName: cm-nayuta-subscribe-test-topic-raw
        
  Queue:
    Type: AWS::SQS::Queue
    Properties:
      QueueName: cm-nayuta-subscribe-test-queue-raw
  QueuePolicy:
    Type: AWS::SQS::QueuePolicy
    Properties:
      Queues:
        - !Ref Queue
      PolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal: "*"
            Action:
              - sqs:SendMessage
            Resource: "*"
            Condition:
              ArnEquals:
                aws:SourceArn: !Ref myTopic
      
  SnsSubscription:
    Type: AWS::SNS::Subscription
    Properties:
      Protocol: sqs
      Endpoint: !GetAtt Queue.Arn
      TopicArn: !Ref myTopic
      RawMessageDelivery: 'true'

これらのテンプレートを使ってCFnにスタックを作っておきます。

やってみる

手順

SNSトピックから、テストメッセージを送ります。

※ 2つ構成があるので、画像は片方のものを記載します。

作成したSNSトピックからメッセージの発行を押します。 メッセージの発行

トピックへのメッセージの発行画面でメッセージ本文を入力します。

{"message": "test"}

メッセージ入力

入力できたらメッセージの発行を押します。

続いて、サブスクライブしているSQSでメッセージをポーリングし、SNSから受信したメッセージを確認します。

該当のキューでメッセージを送受信を押します。 メッセージを送受信

続いて、メッセージをポーリングを押し、SNSから送信されたメッセージを開きます。

メッセージをポーリング

結果

まず、rawデータ配信を無効にしたメッセージは以下のようになりました。 rawデータ配信無効のメッセージ

一方で、rawデータ配信を有効にしたメッセージは以下のようになりました。

rawデータ配信有効のメッセージ

rawデータ配信を無効にした場合のメッセージのMessageの値のみ受信していることが分かります。

感想

SQSの後続のLambdaがあるような場合に、rawデータ配信を有効にしておくとメッセージ取り出しのロジックがかなり簡単になりそうですね。

また、今回比較した設定はRawMessageDeliverytruefalseの違いだけでしたが、CFnテンプレートにしたおかげで、手軽に環境を複製できるので、とても検証が楽でした。

ちょっとした検証の際にも、積極的にテンプレートを作成して、使いまわせるようにしておくと良いですね。