🚀

【AWS】GuardDutyの検知結果をSlackに自動通知する

2022/06/27に公開


はじめに

ご覧いただきありがとうございます。阿河です。

今までは GuardDutyの脅威検知結果についてEメールアドレス宛に通知をしていたのですが、Slack宛に送信が必要なケースがありました。

そこで今回はGuardDutyの検知結果を、任意のSlackチャンネルに自動送信する方法について書きたいと思います。

対象者

  • AWSを運用中
  • 運用を自動化したい
  • AWSとSlackの連携方法について知りたい

概要

  1. GuardDutyの脅威検知をCloudWatch Logsで確認する
  2. 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に通知する検証を行いました。
御覧いただき ありがとうございました。

MEGAZONE株式会社 Tech Blog

Discussion