表題の件、通知メールの件名はわかりやすいのにしたいよねというニーズに対応すべく、以下参考に試してみた。やったことはほぼこちらの記事の通り。
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も併記されるっぽい。
Events側でもルールとLambda関数が紐付いていることがわかる。ちなみにこれはCloudWatche Eventsの画面から見ているが、同じルールがEventBridgeの画面にも存在するはずである。
メール本文。JSONの生データそのまんま。「人間」の感覚としてはこんなん送られてもなぁ…としか思えないが、“DeleteBucket"の記録があることは一応わかる。
CloudTrailはもういらんので削除。…で、SNSからのメールは件名カスタマイズできるのはわかったが、アラームと組み合わせるとなるとまた別の調整が必要。その辺がわからん。次回の課題。
(追記)後日改良版にトライした
イベント監視 メール本文カスタマイズ版
AWSイベント監視 - CloudTrail + EventBridge + Lambdaでメールカスタマイズ(2)
リソース監視 アラーム通知版
CloudWatchアラーム + SNSからのメール件名をカスタマイズする
本文のカスタマイズ例。これはLambda使ってないけど、今回のコードをアレンジすればできるっぽいからそっちに寄せたい感じ。
CloudWatch アラームの通知メールを少しでも読みやすくしたい
EventBridgeって結局元CloudWatchEventsのことなんだが、まだよくわかっていないのでこの辺も調べておく。
Amazon EventBridgeとは何か