この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
Amazon GuardDutyの通知をみなさんはどうされていますか?色々な通知方法がある中から、Backlogに連携する方法をご紹介します。Backlogへの連携はAWS Lambdaを使い、LambdaのデプロイにはServerless Frameworkを使います。
Backlogに通知し、担当者をアサインし対応内容を記載する
GuardDutyはセキュリティに関する脅威を検出するサービスです。GuardDutyで発生するイベントには、誤検知もありえます。私は普段東京オフィスからAWSコンソールを触っていますが、札幌オフィスに出張しAWSコンソールにログインすると、おそらくGuardDutyのイベントが発生します。普段とは異なるIPアドレスから接続することで検知されることは正常であるものの、実務的には誤検知になります。GuardDutyのイベントが誤検知か判断するために、なんらかの方法で通知を受け取り、担当者が判断する必要があります。backlogを利用すると、対応前/対応中/完了などのステータスを設定できたり、担当者をアサインできます。
backlog設定
backlogの設定と確認を行います。後ほど作成するLambdaでは、APIキーやスペースIDなどを使って課題を投稿します。
APIキーの発行
"個人設定">"API">"登録"から、APIキーを発行します。
スペースIDの確認
backlogのURLの一部(https://[スペースID].backlog.jp
)がスペースIDになっています。
プロジェクトIDの確認
backlogのプロジェクト設定を開くとURLに、「project.id=12345」といった形で表示されます。
課題の作成とIDの確認
backlogのプロジェクト設定>種別>種別の追加から、「GuardDuty通知」のような種類を追加します。追加した種別を選択すると、「issueType.id=123456」といった形で表示されます。
プラグインによるパッケージ管理
LambdaはPython3.7で実行しました。 Lambda関数でrequestsパッケージを呼び出します。 パッケージ管理にserverless-python-requirementsプラグインを利用します。 serverlessのブログを参考にしました。プラグインとrequestモジュールをインストールします。
npm install --save serverless-python-requirements
pip install requests
pip freeze > requirements.txt
プラグインの実行にはDockerが必要です。 Dockerデーモンを起動しておきます。
providedテンプレートの作成
Serverless Frameworkの設定に移ります。以下のコマンドを実行すると、serverless.yml、handler.pyのテンプレートが作成されます。
serverless create -t aws-python3 -n guardduty2backlog
ファイルの記載
3つのファイルを作成します。
- serverless.yml(serverless frameworkの設定ファイル)
- handler.py(Lambda関数)
- sample-guardduty-event.json(テスト用のCloudWatchイベントファイル)
serverless.yml
Serverless Frameworkの設定ファイルです。 Lambda関数の設定、CloudWatch Events、GuardDutyの有効化、serverless-python-requirementsプラグインの設定を記載しています。environment
には、backlog設定で確認した内容を記載します。
service: guardduty2backlog
provider:
name: aws
runtime: python3.7
# you can overwrite defaults here
stage: prod
region: ap-northeast-1
# you can add packaging information here
package:
exclude:
- consolelogin.json
functions:
main:
handler: handler.main
events:
- cloudwatchEvent:
event:
source:
- "aws.guardduty"
detail-type:
- "GuardDuty Finding"
# Define function environment variables here
environment:
api_key: '' # backlog's API Key
space_key: '' # classmethod backlog space key
project_id: '' # backlog project id
issue_type_id: '' # backlog issue type id.
priority_id: '3' # backlog priority. normal = 3
plugins:
- serverless-python-requirements
custom:
pythonRequirements:
dockerizePip: true
resources: # CloudFormation template syntax
Resources:
GDD:
Type: "AWS::GuardDuty::Detector"
Properties:
Enable: true
handler.py
Lambda関数です。GuardDutyのイベントの内容を変数に格納してから、POSTします。BASE_URLは環境によって、backlog.com
かbacklog.jp
を選びます。
# -*- coding: utf-8 -*-
import requests
import os
BASE_URL = 'https://{space_key}.backlog.com/api/v2/{api}'
# BASE_URL = 'https://{space_key}.backlog.jp/api/v2/{api}'
api_key = os.environ['api_key']
space_key = os.environ['space_key']
def add_issue(_project_key, _issue_type_id, _priority_id, _summary, _description):
api = 'issues'
url = BASE_URL.format(space_key=space_key, api=api)
payload={
'projectId': _project_key,
'issueTypeId': _issue_type_id,
'priorityId': _priority_id,
'summary': _summary,
'description': _description
}
params = {
'apiKey': api_key,
}
r = requests.post(url, params=params, data=payload)
r.raise_for_status()
return r
def main(event, context):
project_id = os.environ['project_id']
issue_type_id = os.environ['issue_type_id']
priority_id = os.environ['priority_id']
summary = str(event['detail-type'])
if 'detail' in event:
if 'title' in event['detail']:
summary += "(" + str(event['detail']['title']) + ")"
description = "version:" + str(event['version']) + '\n'
messages_keys = ["account","time","region","detail-type"]
for key in messages_keys:
description += key + ":" + str(event[key]) + '\n'
messages_detail_keys = ["accountId","type","title","desctiption","account","region","createdAt","updatedAt"]
for key in messages_detail_keys:
if 'detail' in event:
if key in event['detail']:
description += key + ":" + str(event['detail'][key]) + '\n'
add_issue(project_id, issue_type_id, priority_id, summary, description)
sample-guardduty-event.json
CloudWatchイベントのルールの作成からAWS コンソールのサインインを選択すると、サンプルイベントを表示できます。jsonが表示されるのでコピーアンドペーストしsample-guardduty-event.jsonを作成します。
デプロイ
デプロイコマンドを実行します。
sls deploy
サンプルイベントを使って、テストします。 backlog課題が作成されれば、成功です。
sls invoke -f main -p consolelogin.json
GuardDutyは全てのリージョンで有効にすることが推奨されます。他のリージョンについても、デプロイします。オレゴンリージョンへのデプロイは以下のように行います。
sls deploy --region us-west-2
backlog運用イメージ
GuardDutyのイベントが発生すると以下のように課題が作成されます。
担当者をアサインし確認します。イベントの調査内容を記載したら、完了にします。
動作テストで発生した課題はまとめてクローズできます。
さいごに
Amazon GuardDutyのイベントをbacklogに連携する方法をご紹介しました。GuardDutyでイベントが発生したら誤検知か確認する必要があります。backlogに連携することでステータスや担当者、対応内容を管理できます。
参考
検証環境
Mac OSで以下のバージョンで検証しました。
$ serverless -v
Framework Core: 1.50.0
Plugin: 1.3.8
SDK: 2.1.0
$