こんにちは、サービス開発部のくればやしです。
今回は、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.
方法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の開発に従事。ドラクエ部。推しナンバーはⅤ、推しモンスターはクックルー。