AWS Systems Manager Run Commandの実行結果をSlackに通知する方法

どうも、7月中旬から1~3ヶ月のレンジでホーチミンでリモートワークをする予定のため、今からとても楽しみな古川です。

今回はタイトルの通り、AWS Systems Manager Run Commandの実行結果をSlackに通知する方法を共有したいと思います。

処理フロー

AWS Systems Manager Run Command -> Amazon SNS -> AWS Lambda -> Slack

前提

  1. AWS Systems Manager Run Commandを実行するメンテナンスウィンドウを作成済み
  2. AWS Systems Manager Run Commandのドキュメントは AWS-RunPatchBaseline の想定とする
  3. Slackへの通知はIncoming Webhookで作成した Webhook URL を対象に行い、既に設定が完了しているものとする
  4. AWS LambdaはRubyで作成する

作業の大まかな流れ

  1. Amazon SNSのトピック作成
  2. Slack通知の処理を担当するAWS Lambdaのセットアップ
  3. AWS Systems Manager Run CommandにAmazon SNSを関連づける

実作業

1. Amazon SNSのトピック作成

1-1. IAMロールの作成

URLの「タスク 1: Amazon SNS 通知の IAM ロールを作成する」、「タスク 2: iam:PassRole ポリシーを Amazon SNS ロールにアタッチする」に従いIAMロールを作成。

後述の「4. AWS Systems Manager Run CommandにAmazon SNSを関連づける」内で使用する想定。

上記手順により、以下のような設定のIAMロールが作成される。


※ インラインポリシーが作成されているか要確認。

1-2. トピックの作成

Amazon SNS管理コンソール上でトピックの作成をクリック。

名前を入力して保存。

2.AWS Lambdaのセットアップ

2-1. AWS Lambdaを作成

ランタイムをRuby2.5とし、Lambdaを作成。

作成したLambdaの「コードエントリタイプ」を「コードをインラインで編集」にして以下のコードを main.rb というファイル名で作成。ハンドラを「 main.lambda_handler 」とする。

コード
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
require 'uri'
require 'net/http'
require 'json'

def color_by(status)
color = ""
case status
when "Failed"
color = "danger"
when "Success"
color = "good"
when "InProgress"
color = "#16B0FF" #skyblue
else
color = "warning"
end
color
end

def make_notification_text(subject, msg)
content = {
"Subject" => subject,
"CommandID" => msg["commandId"],
"Status" => msg["status"],
"DocumentName" => msg["documentName"],
"InstanceID" => msg["instanceId"],
"RequestedDatetime" => msg["requestedDateTime"],
"EventTime" => msg["eventTime"]
}

text = ""
content.each do |k, v|
text << "*#{k}:*\n#{v}\n\n"
end
text
end

def lambda_handler(event:, context:)
puts event
event["Records"].each do |record|
msg = JSON.parse(record["Sns"]["Message"])

# HTTPSで通信するための設定
uri = URI.parse(ENV['SLACK_HOOK_URL'])
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
req = Net::HTTP::Post.new(uri.path, initheader = { 'Content-Type' => 'application/json' })

# attachmentsをキーとすることでSlackの通知メッセージにcolorをセット
# 参考: https://api.slack.com/docs/message-attachments
req.body = { "attachments": [{ "text" => make_notification_text(record["Sns"]["Subject"], msg), "color" => color_by(msg["status"]) }] }.to_json
res = http.request(req)
puts "Response #{res.code} #{res.message}: #{res.body}"
end
end

2-2. 環境変数の設定

Lambdaの環境変数設定にて環境変数をセットする。

SLACK_HOOK_URL というキーで Incoming Webhook で作成してある Webhook URL をセットする。

2-3. Amazon SNSのトリガーを追加

AWS LambdaにAmazon SNSのトリガーを追加。
設定するARNは「1. Amazon SNSのトピック作成」の手順で作成したAmazon SNSのトピックのものとする。

2-4. 実行ロールの設定

AWSLambdaBasicExecutionRole のポリシーがアタッチされたロールを「実行ロール」にて選択。

3. AWS Systems Manager Run CommandにAmazon SNSを関連づける

既に作成されているAWS Systems Managerのメンテナンスウィンドウより操作。

↓のように対象のメンテナンスウィンドウの「タスク」より①、②と順番にクリックし編集画面へ移動。

編集画面下部に↓の編集項目があるのでそれぞれ値を入力し保存する。

① - チェックをし有効化。
② - 前述の「1. Amazon SNSのトピック作成」の「1-1. IAMロールの作成」で作成したIAMロールを選択。
③ - 前述の「1. Amazon SNSのトピック作成」の「1-2. トピックの作成」で作成したトピックのARNを入力。

以上の設定が完了次第、AWS Systems Manager Run Commandの実行結果が、以下のような形式でSlackへと通知が行くようになります。
ステータスごとに色が変わるので一見してわかりやすくて良いですね。




このエントリーをはてなブックマークに追加