10
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Amazon GuardDutyの検知結果をSlackへ通知

Last updated at Posted at 2017-12-25

##概要
先日、AWS re:Invent2017でAmazon GuardDuty(※)が発表されました。
これは数クリックで簡単にAWSアカウント上の脅威・リスクを検知するフルマネージドのサービスです。
※Amazon GuardDuty概要

脅威検知した際の通知についてはSNSを利用する等、自分で設定する必要がありますので
Slack/OpsGenieへ通知してみました。:surfer:    

##AWS GuardDutyの導入方法
事前準備としてチェック対象ログ(CloudTrail、VPCフローログなど)の取得を開始しておく必要があります。設定していれば、このボタンをクリックし有効化するだけです。
guardduty01.PNG

##通知してみる
今回はLambdaを使ってSlackとOpsGenieへ通知する2パターンを試してみました。
※それぞれ他ツールと連携するための事前準備手順については省略します。
 (Slack Incoming Webhooksの設定、OpsGenieのAPIキー発行など)

###1-1. Slackへ通知したい場合

  • Slackへ通知するLambda関数(コードは後述)を登録し、あわせて下記環境変数を登録します。
    • slack Webhook URLとして "SLACK_URL" を登録
    • 同様に投稿先のChannelとして "SLACK_CHANNEL" を登録
slack用サンプルコード
#!/usr/bin/env python2
#-*- coding: utf-8 -*-
import os
import json
import logging
from urllib2 import Request, urlopen, URLError, HTTPError

logger = logging.getLogger()
logger.setLevel(logging.INFO)

slack_url = os.environ['SLACK_URL']
slack_channel = os.environ['SLACK_CHANNEL']

def guard2slack(event, context):
    detail = event['detail']
    description = detail['description']
    type = detail['type']
    date = detail['service']['eventFirstSeen']
    severity = detail['severity']
    text = str(type) + '検知!!\n 日時: ' + str(date) + \
            '\n 詳細: '+ str(description) + \
            '\n 深刻度: ' + str(severity)

    if severity < 6:
        color = "warning"
        emoji = ":fearful:"
        message = text
    else:
        color = "danger"
        emoji = ":cold_sweat:"
        message = '<!here>' + text
    
    slack_message = {
        'channel': slack_channel,
        'username': "AWS Check",
        'icon_emoji' : emoji,
        'attachments': [
                        {
                            'color': color,
                            'text': message,
                            'title': "GuardDuty"
                        }
                       ]
        }

    r = Request(slack_url, json.dumps(slack_message))
    try:
        response = urlopen(r)
        response.read()
    except HTTPError as e:
        logger.error("HTTP Error: %d %s", e.code, e.reason)
    except URLError as e:
        logger.error("URL Error: %s", e.reason)

###1-2. OpsGenieへ通知したい場合

  • OpsGenieへ通知するLambda関数(コードは後述)を登録し、あわせて下記環境変数を登録します。
    • OpsGenieのAPIキーとして環境変数 "API_KEY" を登録
    • 同様に通知先のチーム名として "TEAMS" を登録
  • コード内にてOpsGenieSDKを利用しているので、
    ローカル環境にてopsgenie-sdkを落としてからコードと一緒にアップロードして下さい。
OpsGenie用サンプルコード
#!/usr/bin/env python2
#-*- coding: utf-8 -*-
import os
import logging
from opsgenie.swagger_client import AlertApi
from opsgenie.swagger_client import configuration
from opsgenie.swagger_client.models import *
from opsgenie.swagger_client.rest import ApiException

logger = logging.getLogger()
logger.setLevel(logging.INFO)

api_key = os.environ['API_KEY']
teams = os.environ['TEAMS']

configuration.api_key['Authorization'] = api_key
configuration.api_key_prefix['Authorization'] = 'GenieKey'

def guard2ops(event, context):
    detail = event['detail']
    description = detail['description']
    type = detail['type']
    date = detail['service']['eventFirstSeen']
    severity = detail['severity']
    if severity < 6:
         priority='P3'
    else:
         priority='P1'
    text = str(type) + '検知!!\n 日時: ' + str(date) + \
            '\n 詳細: '+ str(description) + \
            '\n 深刻度: ' + str(severity)

    body = CreateAlertRequest(
        message= 'GuardDuty Alart: '+ str(type),
        description=text,
        teams=[TeamRecipient(name=teams)],
        visible_to=[TeamRecipient(name=teams, type='team')],
        entity='GuardDuty',
        priority=priority)

    try:
        response = AlertApi().create_alert(body=body)
        logger.info('request id: {}'.format(response.request_id))
        logger.info('took: {}'.format(response.took))
        logger.info('result: {}'.format(response.result))
    except ApiException as err:
        logger.error("Exception when calling AlertApi->create_alert: %s\n" % err)

###2. CloudWatchイベント設定
最後にCloudWatchイベントのルール設定画面にて
サービス名:GuardDuty、イベントタイプ:GuardDuty Findingを選択し、
ターゲットとして作成したLambda関数を指定します。
guardduty03.PNG

###動作確認

  • GuardDutyコンソール画面にて脅威検出時の結果サンプルを入手可能ですので、このサンプルを使って動作確認が可能です。
    ※注意:サンプルは大量に生成されるため、生成する場合は通知設定前 or 解除して取得することをお勧めします。
    guardduty06.PNG

  • サンプルイベントを使って無事に通知の確認をすることができました。

    • Slack
      guardduty04.PNG
    • OpsGenie
      guardduty05.PNG

##まとめ
GuardDuty × Lambdaで脅威リスクを検知したら自動通知する仕組みを簡単に実現することができました。

あとは深刻度に応じた通知先/通知範囲や検出時の対応など運用ルールを詰めた上で実装していけば、
AWS環境のセキュリティインシデント対応の自動化、セキュリティレベル向上に貢献できそうです。

##参考
OpsGenie python SDK: https://github.com/opsgenie/opsgenie-python-sdk

10
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?