CloudFormationのForEachのループ処理を利用し、パラメータに記載した複数のメールアドレスを1つのSNSトピックに一括登録してみた
はじめに
AWS CloudFormationを使って、Amazon SNSの一つのトピックへ複数のメールアドレスをサブスクリプションとして登録したいケースがありました。
具体的には、新規アカウント発行後に、アカウントへの初期設定として、複数の担当者へ通知を送るためのSNSトピックを作成するCloudFormationテンプレートが必要でした。
このテンプレートは、各アカウントによって担当者や人数は変わることから、サブスクリプションするメールアドレスを動的に変更できる設定が求められました。
例えば、担当者が5名の場合、作成するSNSトピックは、以下のイメージです。
これを実現するためのテンプレートについて解説します。
ForEach関数を利用したテンプレート
複数のメールアドレスをSNSトピックに登録するためのテンプレートは以下のようになります
AWSTemplateFormatVersion: 2010-09-09 Transform: AWS::LanguageExtensions Description: SNS Sample Stack Parameters: SnsTopicName: Description: Topic name Type: String Default: notify-mail-sns MailAddressDomain: Description: Domain name of mail address Type: String Default: example.com AddressUserList: Description: User name of mail address Type: List<String> Default: test1,test2,test3,test4,test5 Resources: SnsTopic: Type: AWS::SNS::Topic Properties: TopicName: !Ref SnsTopicName Fn::ForEach::UserName: - MailAddressUserName - !Ref AddressUserList - Topic${MailAddressUserName}: Type: AWS::SNS::Subscription Properties: Endpoint: !Sub ${MailAddressUserName}@${MailAddressDomain} Protocol: email TopicArn: !Ref SnsTopic
例として、以下のメールアドレスを1つのサブスクリプションに登録するSNSトピックを作成します。
- test1@example.com
- test2@example.com
- test3@example.com
- test4@example.com
- test5@example.com
メールアドレスというのは、ユーザー名と、@、ドメイン名で構成されています。(ユーザー名
@ドメイン名
)
それぞれに対応するパラメータは以下のとおりです
AddressUserList
:メールアドレスのユーザー名をカンマ区切りで入力します。MailAddressDomain
:ドメイン名SnsTopicName
:作成するSNSトピックの名前
この設定でスタックを作成すると、5つのメールアドレスに対して通知するSNSのトピックが作成されます。
パラメータのAddressUserList
に担当者のメールアドレスのユーザー名を入力するだけで、テンプレートのForEach関数がそれぞれのアドレスを1つのSNSトピックにサブスクライブします。
ドメインが異なるメールアドレス
ただし、上記テンプレートの例では、ドメインが異なるメールアドレスを登録することができません。
原因は、CloudFormationの論理IDには、英数字のみが有効であるためです。
論理IDとは、CloudFormationテンプレート内でリソースを一意に識別するための名前です。特殊文字(「@」「:」「-」など)を含めることはできません。
そのため、下記のように、メールアドレスをパラメータに入れてForEach関数を利用すると、23行目のOutputKeyは、論理IDになりますので、Topictest1@example.com
やTopictest2@example.com
が論理IDとなり、エラーになります。
したがって、メールアドレス全体をパラメータとしてForEach関数を利用すると、23行目のOutputKeyが、論理IDになりますので、Topictest1@example.com
やTopictest2@example.com
が許可されない形式となり、エラーが発生します。
AWSTemplateFormatVersion: 2010-09-09 Transform: AWS::LanguageExtensions Description: SNS Sample Stack Parameters: SnsTopicName: Description: Topic name Type: String Default: notify-mail-sns MailAddressList: Description: User name of mail address Type: List<String> Default: test1@example.com,test2@example.org,test3@example.net Resources: SnsTopic: Type: AWS::SNS::Topic Properties: TopicName: !Ref SnsTopicName Fn::ForEach::UserName: - MailAddress<img src="https://d1tlzifd8jdoy4.cloudfront.net/wp-content/uploads/2023/08/b89a5dca19b12db09ba8e0bde4ee33ef-640x239.png" alt="" width="640" height="239" class="alignnone size-medium wp-image-1130213" /> - !Ref MailAddressList - Topic${MailAddress}: Type: AWS::SNS::Subscription Properties: Endpoint: !Ref MailAddress Protocol: email TopicArn: !Ref SnsTopic
以下が実際のエラー内容です。OutputKeyは、英数字のみにするよう怒られています。
Transform AWS::LanguageExtensions failed with: OutputKey 'Topictest1@example.com' should be alphanumeric. Rollback requested by user.
回避方法があれば教えていただきたいです。。
Conditionsを利用したテンプレート
不格好ですが、Conditionsセクションを利用してドメインが異なるメールアドレスを登録することが可能です
AWSTemplateFormatVersion: 2010-09-09 Description: SNS Sample Stack Parameters: SnsTopicName: Description: Topic name Type: String Default: notify-mail-sns MailAddress1: Description: Email address to add to SNS Type: String Default: test1@example.org MailAddress2: Description: Email address to add to SNS Type: String Default: test2@example.com MailAddress3: Description: Email address to add to SNS Type: String Conditions: IsMail1Set: !Not [!Equals [!Ref MailAddress1, '']] IsMail2Set: !Not [!Equals [!Ref MailAddress2, '']] IsMail3Set: !Not [!Equals [!Ref MailAddress3, '']] Resources: SnsTopic: Type: AWS::SNS::Topic Properties: TopicName: !Ref SnsTopicName Mail1Subscription: Type: AWS::SNS::Subscription Condition: IsMail1Set Properties: Endpoint: !Ref MailAddress1 Protocol: email TopicArn: !Ref SnsTopic Mail2Subscription: Type: AWS::SNS::Subscription Condition: IsMail2Set Properties: Endpoint: !Ref MailAddress2 Protocol: email TopicArn: !Ref SnsTopic Mail3Subscription: Type: AWS::SNS::Subscription Condition: IsMail3Set Properties: Endpoint: !Ref MailAddress3 Protocol: email TopicArn: !Ref SnsTopic
例として、以下のメールアドレスを1つのサブスクリプションに登録するSNSトピックを作成します。
- test1@example.org
- test2@example.com
- test3@example.net
各メールアドレスに対応するパラメータは以下の通りです
MailAddress1
、MailAddress2
、MailAddres3
:登録するメールアドレスSnsTopicName
: 作成するSNSトピックの名前
この設定でスタックを作成すると、3つのメールアドレスが通知対象とするSNSのトピックが作成されます。
パラメータMailAddress1
, MailAddress2
, MailAddress3
には通知を受け取りたいメールアドレスを記載します。
もし、2つだけが必要な場合には、MailAddress3
を空白にしておけばOKです。
4人以上のメールアドレスが必要な場合は、テンプレートのConditionsセクションとResourcesセクションを適宜増やすだけです。
必要になるメールアドレス上限数分をテンプレートに作成しておくとよいでしょう。