【CloudFormation/SAM】Amazon SNSトピックのサブスクリプションの作り方3つの方法

記事タイトルとURLをコピーする

こんにちは、サービス開発部のくればやしです。

今回は、CloudFormation(SAM)を使ってAmazon SNS トピックのサブスクリプション(エンドポイントタイプはLambda関数を想定)を作成する方法を紹介します。

サブスクリプションの作り方は大まかに3パターンあるため、それぞれの方法を紹介します。

前提: トピックとサブスクリプションの関係

CloudFormationによる作成方法の説明の前に、Amazon SNSのトピックとサブスクリプションの関係についておさらいしておきます。

ユーザはトピックをまず作成し、そのトピックにLambda関数やメール等のサブスクリプションを登録します。そのトピックにメッセージを送信すると、登録されているサブスクリプションにメッセージを送信されます。トピックとサブスクリプションの間にはフィルタポリシーを設定することもでき、メッセージを送信するかしないかの制御が可能です。

トピックとサブスクリプションの関係は、マネジメントコンソールを見るとイメージしやすいと思います。以下はTopicの詳細画面で、赤枠は設定されているサブスクリプションです。

CloudFormation(SAM)での作成方法

さて、それでは以下で、CloudFormationでのSNSトピックおよびサブスクリプションの作成方法を説明します。

方法1: AWS::SNS::Topic の Properties にサブスクリプションを設定する

以下のように AWS::SNS::Topic の Properties -> Subscription にLambda関数等を登録することで、サブスクリプションを設定できます。

  SNSTopic:
    Type: AWS::SNS::Topic
    Properties:
      TopicName: myTopic
      Subscription:
        - Endpoint: arn:aws:lambda:us-east-1:xxxxxxxxxxxxxx:function:hello
          Protocol: lambda

ただし、以下のドキュメントに記載があるように、細かい部分までサブスクリプションの設定を行いたい場合は、 AWS::SNS::Subscription リソースを使う必要があります。(方法2)

For full control over subscription behavior (for example, delivery policy, filtering, raw message delivery, and cross-region subscriptions), use the AWS::SNS::Subscription resource.

AWS::SNS::Topic Subscription - AWS CloudFormation

方法2: AWS::SNS::Subscription リソースを使ってサブスクリプションを設定する

前述したとおり、以下のように AWS::SNS::Subscription リソースを Topic とは分けて作成することで、サブスクリプションを設定することも出来ます。

  SNSTopic:
    Type: AWS::SNS::Topic
    Properties:
      TopicName: myTopic
  Subscription:
    Type: AWS::SNS::Subscription
    Properties:
      TopicArn: !Ref SNSTopic
      Endpoint: arn:aws:lambda:us-east-1:xxxxxxxxxxx:function:hello
      Protocol: lambda

方法3: AWS::Serverless::Function の Events リソースにTopicを設定する

3つ目の方法として、SAM CLIを使っている場合は、以下のように、AWS::Serverless::Function の Events リソースにTopicを設定することによってもサブスクリプションを作成することができます。ただし、Topicは自動で作成されるわけでは無いので、別のリソースとして定義しておく必要があります。

  SNSTopic3:
    Type: AWS::SNS::Topic
    Properties:
      TopicName: myTopic3

  HelloLambdaFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: src/
      Handler: handler.hello
      Runtime: python3.9
      Events:
        HelloWorld:
          Type: SNS
          Properties:
            Topic: !Ref SNSTopic3

以下に記載のとおり、 AWS::SNS::Subscription リソースが自動で作成されます。 逆にいえば、既存のトピックとサブスクリプションをSAMに AWS::Serverless::Function としてインポートする時には、AWS::Lambda::Function と AWS::SNS::Subscription の指定が必要になります。

このイベントタイプが設定されていると、SAM は AWS::SNS::Subscription リソースを生成します。 SNS - AWS Serverless Application Model

おまけ: 他のIaCツール(Serverless Framework)ではどうなるか?

ちなみに、他のIaCツールであるServerless Frameworkでデプロイするとどうなるかというと、「方法1」の構成でデプロイされます。

例えば、以下のように定義してデプロイすると、

functions:
  hello:
    handler: handler.hello
    events:
      - sns: kuresls

以下のようなCFnテンプレートが展開されます。

  SNSTopicKuresls:
    Type: AWS::SNS::Topic
    Properties:
      TopicName: kuresls
      Subscription:
        - Endpoint: !GetAtt HelloLambdaFunction.Arn
          Protocol: lambda

おわりに

今回、Amazon SNSトピックのサブスクリプションの作り方3つの方法をご紹介しました。

紅林輝(くればやしあきら)(サービス開発部) 記事一覧

サービス開発部所属。2015年にサーバーワークスにJOIN。クラウドインテグレーション部を経て、現在はCloud Automatorの開発に従事。ドラクエ部。推しナンバーはⅤ、推しモンスターはクックルー。