CloudFormationスタック完了時だけメールを受信する
前回のエントリで、スタックイベントをメールで受信できるようになりました。
しかし、全てのイベントを受信するため、大量のメールが届きます。
完了時だけひょっこりメールを受け取りたい!!
最初は、メッセージのフィルタリング機能を使えばできると思ったのですが、メッセージ属性
に対してのフィルタリングであって メッセージ本文
ではできません。
そこで、間に AWS Lambda
を挟んで、完了イベントのみ再通知する仕組みを検討します。
概要
大まかな流れは以下になります。
- ユーザーがスタックを作成
- CloudFormationがスタックイベントをLambdaに送信
- Lambdaでメッセージをチェック、スタックの完了メッセージならSNSメール送信
- ユーザーがメールを受信
トピックの作成
Lambda用とMail用の2つのトピックを作成します。
サービス [アプリケーション統合] - [Simple Notification Service] を選択して、Lambda用のトピックを作成します。
Lambda用
- トピック名:
cloudformation_filter
- サブスクリプション
- ここでは作成しません。(Lambda作成時に作成される)
Mail用
- トピック名:
cloudformation
- サブスクリプション
- プロトコル:
Email
- エンドポイント:
送信したいメールアドレス
- プロトコル:
Mail用は前回の記事を参照してください。
AWS Lambdaの作成
次にLambdaを作成します。
サービス [コンピューティング] - [Lambda] を選択し、[関数の作成]ボタンをクリックします。
関数の作成
- 設計図を選択
- テキストボックスに
sns
と入力してEnterキー、設計図をフィルタリング sns-message
を選択- [設定]ボタンをクリック
基本的な情報
- 名前:
filterMessage
- ロール:
テンプレートから新しいロールを作成
- ロール名:
lambda_send_sns
- ポリシーテンプレート:
SNN 発行ポリシー
SNSトリガー
- SNSトピック:
cloudformation_filter
- トリガーの有効化:
ON
問題なければ、[関数の作成]ボタンをクリックします。
Designer
Lambdaの左側に SNS
、右側にAmazon CloudWatch
とAmazon SNS
が表示されていることを確認します。
関数コード
以下のコードを入力します。
************は自身のAWSアカウントを指定してください。
var aws = require('aws-sdk'); var sns = new aws.SNS(); let result = {}; exports.handler = async (event, context) => { try { const mail = event.Records[0].Sns; const found = mail.Message.match(/^(?=[\s\S]*ResourceStatus='CREATE_COMPLETE')(?=[\s\S]*ResourceType='AWS::CloudFormation::Stack')/); if (found) { result = await sns.publish({ Subject: mail.Subject, Message: mail.Message, TopicArn: "arn:aws:sns:ap-northeast-1:************:cloudformation" }).promise(); } } catch (err) { console.log(err); return err; } return result; };
補足
- デフォルトのランタイムは
Node.js 8.10
です。async, await, promiseを利用しています。 - 改行を含む文字列、メッセージ内に
ResourceStatus='CREATE_COMPLETE'
かつResourceType='AWS::CloudFormation::Stack'
を含む正規表現でチェックしています。 - メールの件名と本文は、受信したメールをそのまま設定しています。わかりやすい内容に変更してください。
Lambdaの保存
右上の[保存]ボタンをクリックします。
「保存されました。」と表示されれば正常です。
Lambdaのテスト
メールが受信できるか確認をします。
[テスト]ボタンをクリックして、テストイベントの設定をします。
- 新しいテストイベントの作成:
ON
- イベントテンプレート:
SNS
- イベント名:
myEvent
JSON文字列内の "Message" 値を変更します。
"Message": "ResourceStatus='CREATE_COMPLETE' ResourceType='AWS::CloudFormation::Stack'"
[作成]ボタンをクリック、テストイベントmyEvent
が選択されている状態で、再度[テスト]ボタンをクリックします。
メールが届けば成功です。これで準備が整いました。
CloudFormationスタックの作成
スタックの作成時にLambda用のトピックを指定します。
既存のAmazon SNSトピックでLambda用のcloudformation_filter
を選択します。
スタック作成後、メールが1件だけ届いたでしょうか?
まとめ
AWS Lambdaを挟むことによって、メールをフィルタリングすることが出来ました。 今回はメール通知ですが、Slackに通知したりするのも面白そうです。
参考
- AWSドキュメント
- AWS Compute Blog