前回投稿した「OSパッチ適用を自動化」させた後、結果をメールに通知させる方法をまとめてみました。
OSパッチ適用を自動化させる方法はこちらをご参照ください。

アーキテクチャ
今回は赤枠内を実装してみました。
Amazon CloudWatch Logs に出力されたログから、指定した任意の文字列をトリガーに Amazon SNS 経由で適用結果をメールで通知する関数を作成します。
AWS Lambdaとは、
サーバーをプロビジョニングまたは管理することなくコードを実行することができるサービスです。
https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/welcome.html
Amazon SNSとは、
Amazon Data Firehose、Amazon SQS、AWS Lambda、HTTP、電子メール、モバイルプッシュ通知、モバイルテキストメッセージ (SMS) などのサポートされているエンドポイントタイプを使用して、クライアントが公開されたメッセージを受信することができるサービスです。
https://docs.aws.amazon.com/sns/latest/dg/welcome.html
設定手順
前回設定したOS「Windows2022」のEC2にパッチ適用した結果を、メール通知させる手順をまとめました。
1.トピックの作成
2.サブスクリプションの作成
3.Lambda関数の作成
4.Lambda サブスクリプションフィルターの作成
1.トピックの作成
Amazon SNSの左メニュー「トピック」をクリックし、「トピックの作成」をクリックします。
▼ 詳細
「タイプ」欄は、「スタンダード」を選択します。
「名前」欄は、任意のトピック名を入力します。
「表示名」欄は、任意の表示名を入力します(表示名が実際のメール差出人の名前になります)。
以下の欄はデフォルトのままにし、「トピックの作成」をクリックします。
▼暗号化 – オプション
▼アクセスポリシー – オプション
▼データ保護ポリシー – オプション
▼配信ポリシー (HTTP/S) – オプション
▼配信ステータスのログ記録 – オプション
▼タグ – オプション
▼アクティブトレース – オプション
2.サブスクリプションの作成
作成したトピックから、「サブスクリプションの作成」をクリックします。
▼ 詳細
「プロトコル」欄は、「Eメール」を選択します。
「エンドポイント」欄は、通知先のメールアドレスを入力します。
以下の欄はデフォルトのままにし、「サブスクリプションの作成」をクリックします。
▼サブスクリプションフィルターポリシー – オプション
▼Redrive ポリシー (デッドレターキュー) – オプション
しばらくすると、指定したアドレス宛に確認のメールが届くので、「Confirm Subscription」をクリックし、「Subscription confirmed!」が表示されることを確認する。
サブスクリプションのステータスが「確認済み」になっていることを確認する。
3.Lambda関数の作成
Lambdaの左メニュー「関数」をクリックし、「関数を作成」をクリックします。
▼ 関数の作成
「一から作成」を選択します。
▼ 基本的な情報
「関数」欄は、任意の関数名を入力します。
「ランタイム」欄は、Lambda関数で記述するプログラミング言語を選択します。
今回はPythonを選択しました。
▼ アクセス権限
「実行ロール」欄は、適切なアクセス権が付与された任意のロールを選択します。
以下の欄はデフォルトのままにし、「関数の作成」をクリックします。
▼ その他の構成
▼ コード
コードソースを以下のコードに修正し、「Deploy」をクリックする。
※Deployをクリックしないと、変更が反映されないので注意してください。
import logging import json import base64 import gzip import boto3 import os logger = logging.getLogger() logger.setLevel(logging.INFO) def lambda_handler(event, context): # CloudWatchLogsからのデータはbase64エンコードされているのでデコード decoded_data = base64.b64decode(event['awslogs']['data']) # バイナリに圧縮されているため展開 json_data = json.loads(gzip.decompress(decoded_data)) logger.info("EVENT: " + json.dumps(json_data)) # ログデータ取得 log = json_data['logEvents'][0]['message'] instanceid_position = log.find('PatchGroup') instanceidtmp = log[:instanceid_position] instanceid = instanceidtmp.replace('Patch Summary for ','') print(instanceid) result_position = log.find('Results') result = log[result_position:] print(result) patchGroup_start = log.find('PatchGroup') patchGroup_end = log.find('BaselineId') patchGrouptmp = log[patchGroup_start:patchGroup_end] patchGroup = patchGrouptmp.replace('PatchGroup : ','') print(patchGroup) messagetmp = """ パッチ適用結果を通知します。 対象インスタンス・適用結果は下記となります。 〇対象インスタンス{0} 〇パッチグループ {1} 〇適用結果 {2} """ message = messagetmp.format(instanceid,patchGroup,result) print(message) try: sns = boto3.client('sns') #SNS Publish publishResponse = sns.publish( TopicArn = os.environ['SNS_TOPIC_ARN'], Message = message, Subject = os.environ['ALARM_SUBJECT'] ) except Exception as e: print(e)
▼ 環境変数
「設定」タブ>「環境変数」にて、「編集」をクリックする。
「環境変数」をクリックし、以下のキーと値を入力し、「保存」をクリックする。
キー | 値 |
ALARM_SUBJECT | パッチ適用通知 |
SNS_TOPIC_ARN | 作成したSNSトピックのARN名 |
4.Lambda サブスクリプションフィルターの作成
CloudWatchの左メニュー「ロググループ」をクリックし、SSMでログの出力先に設定したロググループを検索します。
「サブスクリプションフィルター」タブをクリックし、「作成」>「Lambdaサブスクリプションフィルターを作成」をクリックします。
▼ 送信先を選択
「Lambda関数」欄は、「3.Lambda関数の作成」で作成した関数名を選択します。
▼ ログ形式とフィルターを設定
「ログの形式」欄は、「JSON」を選択します。
「サブスクリプションフィルターのパターン」欄は、フィルターする任意の文字列を入力します。
「サブスクリプションフィルター名」欄は、任意のフィルター名を入力します。
すべての項目を設定後、「ストリーミングを開始」をクリックします。
メール通知確認
パッチ適用完了後に以下のようなメール届くことを確認します。
まとめ
Lambda↔SNS間の通知機能を実装することで、パッチ適用結果の通知にかかわらずあらゆるサービスの状態をメールで受け取ることができるようになります。
皆さんのお役に立てば幸いです。