【AWS】GuardDutyの検知結果をSlackに自動通知する
はじめに
ご覧いただきありがとうございます。阿河です。
今までは GuardDutyの脅威検知結果についてEメールアドレス宛に通知をしていたのですが、Slack宛に送信が必要なケースがありました。
そこで今回はGuardDutyの検知結果を、任意のSlackチャンネルに自動送信する方法について書きたいと思います。
対象者
- AWSを運用中
- 運用を自動化したい
- AWSとSlackの連携方法について知りたい
概要
- GuardDutyの脅威検知をCloudWatch Logsで確認する
- Slack通知を実装
事前準備
- AWSアカウント作成
- AdministratorAccessを付与したIAMユーザーの作成
- GuardDutyを有効化
- 情報を通知するSlackワークスペース/チャンネルの準備
1. GuardDutyの脅威検知をCloudWatch Logsで確認する
Lambda用のIAMロールを作成
- 信頼されるエンティティ: Lambda
- ポリシー: (AWSLambdaBasicExecutionRole)
Lambda関数を作成
- オプション: 一から作成
- ランタイム: Python
- アーキテクチャ: x86_64
- ロール: 作成したロール
Lambdaコードを記述
import boto3
def send_alert(id,type,date,severity):
mail_title = "GuardDuty-Alert-Test"
message = f"アラート内容をご確認ください。\nID: {id}\nタイプ: {type}\n発生日: {date}\n重要度: {severity}"
print(message)
return message
def lambda_handler(event, context):
id = event["detail"]["id"]
type = event["detail"]["type"]
date = event["detail"]["service"]["eventLastSeen"]
severity = event["detail"]["severity"]
send_alert(id,type,date,severity)
return True
EventBridgeのターゲットにLambdaを指定することで、GuardDutyの検知結果をイベントとして受け取ります。
idなど必要なデータを取り出した上で、Slackに送るメッセージにデータを内包します。
現時点ではprintの結果をCloudWatch Logsで確認することにします。
EventBridgeを作成
-
名前: 任意の名前
-
イベントバス: default
-
ルールタイプ: イベントパターンを持つルール
-
イベントパターン: カスタムパターン
今回は"severity"が8.0以上の脅威を対象とします。
{
"source": [
"aws.guardduty"
],
"detail-type": [
"GuardDuty Finding"
],
"detail": {
"severity": [
8,
8.0,
8.1,
8.2,
8.3,
8.4,
8.5,
8.6,
8.7,
8.8,
8.9
]
}
}
- ターゲットタイプ: AWSのサービス
- ターゲット: Lambda関数(作成したLambda関数を指定します)
GuardDutyでサンプルイベントを発生させる
意図的に脅威を発生させることは難しいため、GuardDutyでサンプルイベントを生成してテストを行います。
GuardDutyのページで「設定」⇒「検出結果サンプルの生成」をクリックします。
生成が完了したら、CloudWatch Logsでログを確認します。
ログが確認できるまで数分ほどかかると思います。
print結果が確認できます。
こちらの内容をSlackに通知できるようにします。
2. Slack通知を実装
Slack側の設定
LambdaからSlackの特定チャンネルに通知を送るようにします。
Incoming Webhookを使用します。
外部ソースからの情報を簡単にワークスペースと共有できます。
Slack画面の「App」の画面で、「Appディレクトリ」を選択。
「ビルド」を選択。
「Create an app」を選択。
「From scratch」を選択。
使用するワークスぺースを選択します。
「Basic Information」から「Incoming Webhooks」を選択。
Webhookをアクティブ化した上で、「Add New Webhook to WorkSpace」を選択。
通知を送るチャンネルを指定して、「許可する」をクリック。
設定が完了しました。
Webhook URLをコピーしておきます。
Lambda側の変更
こちらを参考にしながら、Lambdaのコードを変更します。
import urllib3
import json
import boto3
http = urllib3.PoolManager()
def send_alert(id,type,date,severity):
url = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
message = f"アラート内容をご確認ください。\nID: {id}\nタイプ: {type}\n発生日: {date}\n重要度: {severity}"
msg = {
"channel": "#xxxxxxxxxxxxxxxxx",
"username": "",
"text": message,
"icon_emoji": ""
}
encoded_msg = json.dumps(msg).encode('utf-8')
resp = http.request('POST',url, body=encoded_msg)
return resp
def lambda_handler(event, context):
id = event["detail"]["id"]
type = event["detail"]["type"]
date = event["detail"]["service"]["eventLastSeen"]
severity = event["detail"]["severity"]
alert_result = send_alert(id,type,date,severity)
return True
urlとchannelは自身の環境のものに置き換えてください。
検証
では改めてGuardDuty側でサンプルイベントを生成してみましょう。
数分後Slackを確認してみます。
指定したチャンネルに検知結果が通知されています。
Lambda~Slack間の連携は上手くいっているようです。
さいごに
以上、GuardDutyの検知結果をSlackに通知する検証を行いました。
御覧いただき ありがとうございました。
Discussion