EventBridgeとStep Functionsを使ってSecurity Hubの結果をBacklogに自動起票する構成を考えてみた
こんにちは、AWS事業本部@福岡オフィスのべこみん(@beco_minn)です。
皆さん、AWS Security Hub(以下、Security Hub)は使ってますか?
Security HubはAWSの体制管理をしてくれる最高のサービスですよね。
今回はそんなSecurity Hubの結果をBacklogに自動起票するシステムを、Amazon EventBridge(以下、EventBridge)とAWS Step Functions(以下、SFn)を使って組んでみたのでご紹介します。
それでは見ていきましょう。
まずはBacklogのチケット起票APIを確認する
課題の追加 | Backlog Developer API | Nulab
Backlogのチケット起票(課題追加)に利用するAPIの仕様は上記ページの通りです。
この中でも気を付けなければならないのは以下の部分。
リクエストパラメーター
Content-Type:application/x-www-form-urlencodedprojectId (必須)
summary (必須)
issueTypeId (必須)
priorityId (必須)
送信するリクエストはContent-Typeが指定されていて、必須パラメーターが4つあります。
これを念頭に入れてシステムを構成します。
システムの構成
今回の構成では、前述の通り通知のために2つのAWSサービスを利用します。
それぞれの役割を簡単に説明します。
- EventBridge ルール
- Security Hubからのイベントを後続に受け渡す役割
- SFn
- Backlog APIに対してリクエストを送る役割
- 今回はリクエスト内容をURLエンコードする必要があるが、SFnの機能で簡単にそれを実装することが出来るので採用
- EventBridge Connections
- Backlog APIに必要な認証情報を管理する役割
構築の流れとしては以下のように行います。
- BacklogのAPIキーを作成
- Amazon EventBridge Connectionsの設定
- AWS Step Functionsの設定
- Amazon EventBridge ルールの設定
BacklogのAPIキーを作成
まずは上記ページの手順に従い、BacklogのAPIを操作するためのAPIキーを作成します。
Amazon EventBridge Connectionsの設定
次にStep FunctionsのStateMachineにアタッチするためのEventBridge Connectionsを作成します。
作成画面を開き、以下の通り設定します。
- 呼び出しを設定
- APIタイプ
- パブリック
- APIタイプ
- 認証を設定
- カスタム設定
- 認証タイプ
- APIキー(ここで指定するAPIキーはBacklog接続では利用しないため任意の値でOK)
- キー名:
dummy
- 値:
dummy
- キー名:
- 呼び出し Http パラメータ
- パラメータ: クエリ文字列(よりセキュアにしたい方はシークレットのクエリ文字列にしてください)
- キー:
apiKey
- 値: 先ほど取得したBacklogのAPIキー
- APIキー(ここで指定するAPIキーはBacklog接続では利用しないため任意の値でOK)
設定を終えたら作成ボタンを押下します。
AWS Step Functionsの設定
それではStep FunctionsでState Machineを作成します。
利用するアクションは Call HTTPS APIs です。
以下の通りに設定します。
クエリ言語は JSONata です。
- API エンドポイント
https://*****.backlog.jp/api/v2/issues
*****
には通知先のBacklogプロジェクトのドメインを入力してください。
- 接続
- 先ほど作成したEventBridge Connectionを選択
- リクエスト本文
- 後述
- 詳細パラメーター
- ヘッダー - オプション
"Content-Type": "application/x-www-form-urlencoded"
- ヘッダー - オプション
- URL エンコードをリクエスト本文に適用
- チェックをいれる
リクエスト本文には以下を入力します。
projectId と issueTypeId はBacklogプロジェクトから取得した値を入力してください。
priorityIdは「高」が2
、「中」が3
、「低」が4
です。今回は3を指定します。
参考: 優先度一覧の取得 | Backlog Developer API | Nulab
{
"projectId": "1234567890",
"summary": "{% $states.input.summary %}",
"description": "{% $states.input.description %}",
"issueTypeId": "0987654321",
"priorityId": "3"
}
特にこの URL エンコードをリクエスト本文に適用 が大事です。
この状態で作成します。
作成すると上図のように必要なロールを作成する確認画面を出てくるので確認ボタンを押下します。
Amazon EventBridge ルールの設定
それでは最後にEventBridgeのルールを作成します。
今回は default イベントバスで作成しますが、任意のイベントバスで作成して良いです。
「イベントパターンを持つルール」を選択し、次へ。
イベントパターンはカスタムパターンを選択します。
{
"detail-type": ["Security Hub Findings - Imported"],
"source": ["aws.securityhub"],
"detail": {
"findings": {
"Compliance": {
"Status": [{
"anything-but": "PASSED"
}]
},
"RecordState": ["ACTIVE"],
"Workflow": {
"Status": ["NEW"]
},
"Severity": {
"Label": ["CRITICAL", "HIGH"]
}
}
}
}
ターゲットとして先ほど作成したState Machineを選択し、追加設定として入力トランスフォーマーを設定します。
この入力トランスフォーマーはSecurity Hubからの結果をBacklog通知用に整形するためのものです。
入力パス
{
"Description": "$.detail.findings[0].Description",
"Id": "$.detail.findings[0].Id",
"Resource": "$.detail.findings[0].Resources[0].Id",
"Summary": "$.detail.findings[0].Title"
}
テンプレート
{
"summary": <Summary>,
"description": "Description:<br /><Description><br /><br />Resource:<br /><Resource><br /><br />Links:<br />[Security Hub](https://ap-northeast-1.console.aws.amazon.com/securityhub/home?region=ap-northeast-1#/findings?search=Id%3D%255Coperator%255C%253AEQUALS%255C%253A<Id>)"
}
今回は下記記事を参考に、かなり簡素なdescriptionにしました。必要に応じて変更してください。
EventBridge API Destinationsを使ってSecurity Hub検知をBacklogに自動起票してみた | DevelopersIO
通知が飛ぶとこんな感じ。これは EC2.2 の検出結果です。
なぜStep Functionsを採用したのか?
実はEventBridgeにもAPI DestinationsというAPIにリクエストを送る機能が存在するのですが、今回は敢えてStep Functionsを利用しました。
その理由は、リクエストの本文をURLエンコードしたかったからです。
Backlog APIではリクエスト本文のContent-typeが指定されているのですが、EventBridgeだけではリクエストの本文をURLエンコードすることが出来ずJSON形式でリクエストを送ることになります。
そこで、今回はStep Functionsの Call HTTPS APIs にあるリクエスト本文のURLエンコード機能を活用したというわけです。
おまけ: リクエストに必要なBacklogパラメーターの取得方法
リクエストに必要なパラメーターのうち、以下の値は通知先のBacklogプロジェクトから取得する必要があります。
それぞれの取得方法について簡単に記載します。
projectId (必須)
issueTypeId (必須)
これらの値はAPI経由でも取得出来るのですが、今回はローコード開発ということもあるのでBacklogのUI上から取得する方法をご説明します。
まず対象のプロジェクトの課題一覧を開きます。
そこで通知を登録したい課題種別を検索条件として選択します。
すると、URL内に選択した課題種別のIDとプロジェクト自体のIDが含まれているため、数字をコピーします。(下図上部の赤枠部)
これが projectId
と issueTypeId
です。
最後に
今回はBacklog APIの仕様に則り、正しい形で自動起票する構成についてご紹介しました。
少しややこしい構成ではありますが、Lambdaのコードを管理しなくて良いので非常に楽な構成ではないでしょうか。
また、起票課題の優先度をSeverityに合わせて動的にしたい場合でもJSONataで良い感じに書けそうですね。
本記事がどなたかのお役に立てば幸いです。
以上、べこみんでした。