表題の件、通知メールの件名はわかりやすいのにしたいよねというニーズに対応すべく、以下参考に試してみた。やったことはほぼこちらの記事の通り。

Amazon SNS で送られる CloudWatch Events ルールの通知内容をカスタマイズする

 

上記の通りやっていけばできるんだけれど、整理するためにも自分用に記録残す。ちなみに2021年10月現在、CloudWatch EventsはEventBridgeになっている。移行期間中だからまだ違和感があるが、この記事では名称は「EventBridge」とする。それと後半で書いているが、今回の事例ではCloudTrailが有効になっていることが前提なので、現状無効の場合は有効にしておく。

各種リソースに類似の名称が多くて混乱するので、これも自分用に整理。以下、今回作成したリソース名称。

アイテム 名称
SNSトピック custom-event-notification
Lambda用IAMロール custom-event-mail-role
Lambda関数 custom-mail-function
eventルール custom-mail-rule

 

ではここから作業内容の記録に入る。

SNSトピック作成

$ aws sns create-topic --name custom-event-notification

 

サブスク(サブスクリプション)作成

$ aws sns subscribe --topic-arn arn:aws:sns:ap-northeast-1:my-account-id:custom-event-notification --protocol email --notification-endpoint [my mail address]

{
    "SubscriptionArn": "pending confirmation"
}

 

指定したアドレスにメールが届くので、リンク押下してconfirmする。その後マネコンのSNS画面を見るとサブスクのステータスがconfirmedになっているはず。

または、以下確認コマンド

$ aws sns list-subscriptions-by-topic --topic-arn arn:aws:sns:ap-northeast-1:my-account-id:custom-event-notification

 

ここからLambdaの作業に入る。最初にLambda用のIAMロールを作成。以下の内容で信頼ポリシー用のJSONファイルを用意し、それを指定してロール作成実行。

trust-policy.json

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "lambda.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

 

$ aws iam create-role --role-name custom-event-mail-role --assume-role-policy-document file://trust-policy.json

 

ロールにAWSマネージドポリシーをアタッチ。

$ aws iam attach-role-policy --role-name custom-event-mail-role --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
$ aws iam attach-role-policy --role-name custom-event-mail-role --policy-arn arn:aws:iam::aws:policy/AmazonSNSFullAccess

 

ここまでで、IAMロール完成。次に、以下内容のLambda関数のコードを用意する。

custom-mail.py

import boto3
import json
import os

sns_arn = os.environ['SNS_TOPIC_ARN']
custom_subject = os.environ['CUSTOM_SUBJECT']

def lambda_handler(event, context):
    print(sns_arn)
    client = boto3.client("sns")
    resp = client.publish(TargetArn=sns_arn, Message=json.dumps(event), Subject=custom_subject)

 

これをzipにする。

$ zip custom-mail.zip custom-mail.py

 

IAMロールとzipファイルを指定してLambda関数を作成。

$ aws lambda create-function --function-name custom-mail-function --role arn:aws:iam::my-account-id:role/custom-event-mail-role --runtime python3.8 --handler custom-mail.lambda_handler --zip-file fileb://custom-mail.zip

 

環境変数をセット。ここでSNSトピックARNと、送信したいメール件名を定義している。

$ aws lambda update-function-configuration --function-name custom-mail-function --environment Variables='{SNS_TOPIC_ARN="arn:aws:sns:ap-northeast-1:my-account-id:custom-event-notification",CUSTOM_SUBJECT="カスタムメールタイトル送信テスト"}'

 

変数名
SNS_TOPIC_ARN arn:aws:sns:ap-northeast-1:my-account-id:custom-event-notification
CUSTOM_SUBJECT カスタムメールタイトル送信テスト

 

トリガーとなるイベントルールを作成。本当はec2のCPU使用率のアラームでメール飛ばしたいがここは参考ページの通りにする。

event-pattern.json

{
  "source": [
    "aws.s3"
  ],
  "detail-type": [
    "AWS API Call via CloudTrail"
  ],
  "detail": {
    "eventSource": [
      "s3.amazonaws.com"
    ],
    "eventName": [
      "CreateBucket",
      "DeleteBucket"
    ]
  }
}

 

eventsのルールを作成する。

$ aws events put-rule --name custom-mail-rule --event-pattern file://event-pattern.json
{
    "RuleArn": "arn:aws:events:ap-northeast-1:my-account-id:rule/custom-mail-rule"
}

 

Lambdaにルールの実行権限を追加。

$ aws lambda add-permission --function-name custom-mail-function --statement-id 1 --principal events.amazonaws.com --action 'lambda:InvokeFunction' --source-arn arn:aws:events:ap-northeast-1:my-account-id:rule/custom-mail-rule

{
    "Statement": "{\"Sid\":\"1\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"events.amazonaws.com\"},\"Action\":\"lambda:InvokeFunction\",\"Resource\":\"arn:aws:lambda:ap-northeast-1:my-account-id:function:custom-mail-function\",\"Condition\":{\"ArnLike\":{\"AWS:SourceArn\":\"arn:aws:events:ap-northeast-1:my-account-id:rule/custom-mail-rule\"}}}"
}

 

Lambda関数をルールのターゲットとしてセットする。

$ aws events put-targets --rule custom-mail-rule --targets "Id"="Target1","Arn"="arn:aws:lambda:ap-northeast-1:my-account-id:function:custom-mail-function"
{
    "FailedEntryCount": 0,
    "FailedEntries": []
}

 

バケットを作成して通知テスト

$ aws s3 mb s3://custom-mail-sending-test-xxxx

 

…しかしメール届かない。て、CloudTrailが無効になっているんだから当然である。で、CloudTrailを有効にしてから先ほど作成したバケットを消してみる。したら、…設定した件名「カスタムメールタイトル送信テスト」で通知メールが届いた!

Lambda関数の画面ではトリガーがEventBridgeになっているが、移行期間中はカッコでCloudWatche Eventsも併記されるっぽい。

Lambda関数画面 Lambda関数トリガー

 

Events側でもルールとLambda関数が紐付いていることがわかる。ちなみにこれはCloudWatche Eventsの画面から見ているが、同じルールがEventBridgeの画面にも存在するはずである。

Eventsルール画面

 

メール本文。JSONの生データそのまんま。「人間」の感覚としてはこんなん送られてもなぁ…としか思えないが、“DeleteBucket"の記録があることは一応わかる。

カスタム件名メール

 

CloudTrailはもういらんので削除。…で、SNSからのメールは件名カスタマイズできるのはわかったが、アラームと組み合わせるとなるとまた別の調整が必要。その辺がわからん。次回の課題。

(追記)後日改良版にトライした
イベント監視 メール本文カスタマイズ版
AWSイベント監視 - CloudTrail + EventBridge + Lambdaでメールカスタマイズ(2)

リソース監視 アラーム通知版
CloudWatchアラーム + SNSからのメール件名をカスタマイズする

 

本文のカスタマイズ例。これはLambda使ってないけど、今回のコードをアレンジすればできるっぽいからそっちに寄せたい感じ。
CloudWatch アラームの通知メールを少しでも読みやすくしたい

EventBridgeって結局元CloudWatchEventsのことなんだが、まだよくわかっていないのでこの辺も調べておく。
Amazon EventBridgeとは何か

 

東京湾


関連がありそうな記事