EventBridgeとSNSで複数行のメール通知を送る方法をCloudFormationから試してみた

2022.03.24

データアナリティクス事業本部の鈴木です。

最近はAmazon EventBridgeとCloudWatch Alarmを使って、いいかんじのメール通知を送ることに凝っています。

今回はEventBridgeルールの入力トランスフォーマーを使って複数行のメールをSNS経由で送信する設定をCloudFormationからデプロイするのに試行錯誤したので、分かったことをまとめました。

やりたいこと

EventBridgeの入力トランスフォーマーを使って、読みやすいように整形した複数行のメールをメールアドレス宛に送信したいです。

以下のようなメールが届きます。

通知メール例

構成は以下のようなイメージです。

検証したい構成

結論

  • 入力テンプレートに複数行の文字列を登録するとできる。ただし、各行は二重引用符で閉じるようにする。
  • メール本文の各行に"が入ってしまうので、Step Functionsなどを挟むとより綺麗なメールを送ることができた。

やってみる

CloudFormationテンプレートの作成

検証用のCloudFormationテンプレートを作成しました。

SQSのキューからのメトリクスを監視してアラームが発火するように設定してあります。

検証用の構成

テンプレートは以下です。

template.yml

AWSTemplateFormatVersion: 2010-09-09
Description: SQS Standard Queue with alerm & notification

Parameters:
  QueueName:
    Description: Name for queue
    Type: String
  SNSTopicName:
    Description: SNSTopicName for Alarm
    Type: String  
  NotificationTarget:
    Description: Email for notification
    Type: String

Resources:
  # イベント作成用のリソース
  ## SQSキュー
  SQSQueue:
    Type: AWS::SQS::Queue
    Properties:
      MessageRetentionPeriod: 1209600
      QueueName: !Ref QueueName
      VisibilityTimeout: 120

  ## CloudWatch アラーム
  SQSAlarm:
    Type: AWS::CloudWatch::Alarm
    Properties:
      AlarmName: !Sub ${QueueName}-alerm
      ComparisonOperator: GreaterThanThreshold
      DatapointsToAlarm: 1
      EvaluationPeriods: 1
      Threshold: 0
      Namespace: AWS/SQS
      Dimensions:
          - Name: QueueName
            Value: !Ref QueueName
      MetricName: ApproximateNumberOfMessagesVisible
      Period: 60
      Statistic: Maximum
      TreatMissingData: notBreaching

  # アラーム検出・通知用のリソース
  ## SNSトピック
  SnsTopic:
    Type: AWS::SNS::Topic
    Properties: 
      TopicName: !Ref SNSTopicName
      Subscription:
        - Endpoint: !Ref NotificationTarget
          Protocol: email
  ## SNSトピックポリシー
  EventTopicPolicy:
    Type: AWS::SNS::TopicPolicy
    Properties:
      PolicyDocument:
        Statement:
          - Effect: "Allow"
            Principal:
              Service: "events.amazonaws.com"
            Action: "sns:Publish"
            Resource: "*"
      Topics:
        - !Ref SnsTopic
  ## EventBridge
  AlarmEvent:
    Type: AWS::Events::Rule
    Properties: 
      Description: String
      EventPattern: !Sub |
        {
          "source": ["aws.cloudwatch"],
          "detail-type": ["CloudWatch Alarm State Change"],
          "resources": [{"prefix": "arn:aws:cloudwatch:${AWS::Region}:${AWS::AccountId}:alarm:${QueueName}-alerm"}],
          "detail": {"state": {"value": ["ALARM"]}}
        }
      Targets: 
        - Arn: !Ref SnsTopic
          Id: sns-topic
          InputTransformer:
            InputPathsMap:
              "AlarmName": "$.detail.alarmName"
            InputTemplate: |
              "Alarm Change state to Alarm!"
              "Alarm name : <AlarmName>"

ポイントはハイライト箇所です。 InputTemplateにブロックスタイルでメールに記載したい複数行の文字列を渡しています。

各行は"をつけるようにしています。

動作確認

CloudFormationから上記テンプレートをデプロイします。設定したメールアドレスにサブスクリプションの承認メールが届くので、承諾しておきます。

作成されたEventBridgeルールの設定を確認すると、以下のように入力トランスフォーマーが設定されていることが確認できました。

ルールの設定

作成されたSQSキューにメッセージを投入し、しばらくするとCloudWatch Alarmがアラーム状態になるので、それに伴いメールが送られてきました。

通知メール例

気になった点

メールの各行の"は取れないのかな?と思いましたが、以下の公式ドキュメントでも、改行を含むテンプレートを保存する際に Invalid InputTemplate エラーが表示された場合は、各行は必ず二重引用符で閉じるようにしてください。と記載があり、入力トランスフォーマーを使用する際は必要になりそうでした。

入力トランスフォーマーを使用して EventBridge 通知をカスタマイズする

例えば、上記のCloudFormationテンプレートを一部以下のように変えて、スタックをアップデートすると、以下のように失敗しました。

template.ymlの抜粋

      Targets: 
        - Arn: !Ref SnsTopic
          Id: sns-topic
          InputTransformer:
            InputPathsMap:
              "AlarmName": "$.detail.alarmName"
            InputTemplate: |
              Alarm Change state to Alarm!
              Alarm name : <AlarmName>

アップデート結果

CloudFormationからなのが悪いのかな?と思い、作成したEventBridgeルールを手動で変えてみましたが、ドキュメントの通り、Invalid InputTemplate エラーが表示されることが分かりました。

入力テンプレートの修正例

として設定を上書きしようとすると、

入力テンプレートのエラー例

のようにエラーが表示されました。

どうしても体裁が気になる場合は、こちらのブログのように、Step Functionsなどもう一層カスタマイズ用のリソースを挟むことで、件名と併せて設定できたので、参考にしてみてください。

CloudWatchアラームとSNSで日本語の件名・本文のメールを送るためのCloudFormationテンプレートを作ってみた | DevelopersIO

最後に

今回はEventBridgeルールの入力トランスフォーマーを使って複数行のメールをSNS経由で送信する設定をCloudFormationからデプロイするのに試行錯誤した結果をまとめてみました。

初めて使われる方で、特にCloudFormationからデプロイされているようなケースだと、何が問題でデプロイが失敗するのか切り分けが難しかったりするので、参考になりましたら幸いです。

参考