でこてっくろぐ ねお

UbieのSRE。でこらいふろぐ(http://dekolife.hatenablog.com/)の姉妹版。デコテックログ(deko tech log)である

GuardDutyの検知結果をslack投稿するアーキテクチャを考えた(あるいはAWSでイベントのフィルタを行うときに考えたこと)

こちらははてなエンジニア Advent Calendar 2022 - Hatena Developer Blogの46日目です。1/15日の分なのですがフライングでの投稿です(日付を間違えてた)。 昨日は Perlでテーブル駆動テストを書くのにハマっている - NaaN日記でしたね。テーブル駆動テストのことを知ったのは私は数年前にGo言語のテストを書き始めてからですが、いつ頃から流行り始めたのかがちょっと気になる今日この頃です。このエントリにもLambdaのテストについて書いてありますが、このテストコードもテーブル駆動で書いています。テーブル駆動テスト大好きです。

やりたかったこと

色々なチームが相乗りしているAWSアカウントのGuardDutyの検知を、自分のチームに関係のあるイベントだけ通知する、というのを実装したかった。 検知結果を自分のチーム専用にいい感じにフィルタして通知したい、という感じ。

構成案

"GuardDutyをSlackに通知する" みたいなのを検索すると、大体以下2案のどちらかが出てくる。今回はこの2案からどちらを選ぶかを検討した。 ある程度シンプルな形でGuardDutyの結果をslack通知するのであればこれくらいの選択肢しかないだろうと思っているがもっといい案がある人は教えてほしい。

  • 案1: GuardDuty -> EventBridge -> SNS -> ChatBot -> Slack
  • 案2: GuardDuty -> EventBridge -> Lambda -> Slack

どちらの案を選ぶか決める際に考えたこと

案1はLambdaを使わなくても構築できる。つまり、Lambdaのコードを書かなくてもIaC的なコードだけで管理できる、という嬉しさがありそう。

案1でも案2でもGuardDutyの検知結果のslack通知はできるが、上記"やりたかったこと"の内容を考えると、不要な通知をいい感じに排除する機構をどこに設けるかが結構重要なポイントになってくるかなと思う。

一般的には、GuardDutyの抑制ルールでフィルタするものかもしれないが、この抑制ルールはGuardDutyの設定全体に効くものという理解なので、複数チームで1つのアカウントのGuardDutyを見ている状況で自分のチーム向けのルールを設定するのは行えない。

案1だったらAmazon EventBridge のイベントパターンでのフィルターやSNSのメッセージフィルターでフィルタを行うことになりそう。案2だと、Amazon EventBridge のイベントパターン以外に、Lambdaで動かすプログラムで素朴にフィルタするようなコードを書くという選択肢が手に入る。

EventBridge側でフィルタを行うと、後続の処理が走らなくなるのでコスト的な優位性は存在する。ただ、そのAWSアカウントのGuardDutyの検知のオーダーは、日に数百件とか数千件とかくるわけでは全くなく、かつslack通知を行うlambdaも非常に簡単な処理になるので、後続のタスクのコストは考えなくて良い程度のものになる。

また、不要な通知はいい感じに排除する、というのは運用の中でフィルタする条件もどんどん変更されていくことが想定される。 その際にEventBridgeのイベントパターンやSNSのメッセージフィルターを使って実装すると、フィルタの条件が複雑になってくるにつれて"この変更は本当に既存の通知を壊していないだろうか"という不安が大きくなって変更速度が鈍りそう/実際に既存の通知を壊しそう、という懸念が大きいと考えた。 変更の際の安心感を担保するには、テストの書けるLambda側でフィルターを実施するのが簡単であろう。イベントパターンやメッセージフィルターでも簡単にテストができると良いのだが。

結果

上記の通り、フィルタ条件変更時の安心による速度向上を狙って案2で、通知のフィルタをLambdaで実装する方式を採用した。 テストが普通のアプリケーションと同様に書けるのは書きやすいし安心。

気になり

Amazon EventBridge のイベントパターンでのフィルターやSNSのメッセージフィルター を手元から簡単にテストする方法はあるだろうか。 E2Eテスト的なものを作るしかないという認識だが、うまい方法があったら是非とも知りたい。