こんにちは。SREチームのチームリーダーをしている後藤です。
このブログはエムスリー Advent Calendar 2025 7日目の記事になります。
我が家の子供達は今年は初めて(本物の)アドベントカレンダーを手に入れて毎日楽しそうに開封しています。 そんな様子を微笑ましく思いつつ、(テックブログの)アドベントカレンダーをお届けします。
今日はAWSのGuardDutyの通知について書いていきたいと思います。

GuardDutyの活用
GuardDutyはご存知の方が多いと思いますが、AWS環境におけるセキュリティの脅威を検出するためのサービスです。 IAMユーザの不自然な挙動、不自然なAPI呼び出し、EC2からの不審な外部通信などを検知できます。
弊社では2020年にGuardDutyを導入し、AWSのOrganization全体で有効化されるように設定しています。 また、GuardDutyの検出結果はセキュリティの脅威として素早く確認する必要がありますので、EventBridgeを経由してSlackに通知しています。
GuardDutyの通知における課題
GuardDuty導入初期の頃から、通知は各チームの担当者がいる1つのチャンネルに集めていました。 これには、シンプルに始められる、多くの人が目にすることで取りこぼしを減らせるといったメリットがありましたし、通知や対応状況が見えることでセキュリティへの意識を高めることも期待できました。 しかし、OrganizationのAWSアカウント数が増えるにつれて、1つチャンネルに通知を集める方式では次のような課題感が強くなりました。
「検出結果サンプルの生成」による大量通知
GuardDutyのコンソールには「検出結果サンプルの生成」という機能があり、実際にサンプルの検出結果を生成して確認できます。 セキュリティがしっかりしているほど実際に問題が検出される事は稀ですので、サンプルで確認できるのはありがたいことです。
が、この機能を使用すると100を超える大量の検出サンプルが生成されてしまうという罠があります。 結果として本物のアラートと同じチャンネルに大量の通知が届き、いったい何が起こったのかと肝が冷えるわけです。 サンプルの通知であることは内容から明白にわかるのですがかなりのノイズです。
ちなみに1件だけサンプルを生成したい場合はAWS CLIから実現できます。 やり方についてはクラスメソッドさんの記事を引用させて頂きます。
グループ会社管理のAWSアカウントに対する通知
弊社では年々グループ会社が増えてきており、それに伴ってOrganizationにグループ会社管理のAWSアカウントも増えてきました。 グループ会社管理のAWSアカウントに対する通知も同じチャンネルに届くのですが、その場合はまず社内のグループ会社支援チームに連絡して、そこから各社の担当者に連絡して対応してもらうというフローになっていました。 その他のメンバーからすると通知に気づいても対応しづらく、また対応内容や作業が完了したかも見えない状態になっていました。
アラート通知の原則として、このチャンネルに通知がきた = すぐに状況を確認しなければいけないという意識が持てているのが理想です。 しかし、自分には対応できない通知が増えてくるとどうしても意識が薄れていってしまい、結果として対応遅れや取りこぼしの懸念が高まります。
通知を複数チャンネルに振り分ける
課題の解決方法はいたってシンプルで、通知先のチャンネルをいくつかに分けることにしました。 仕組みもEventBridgeのルールで振り分けるだけなので難しくはないのですが、イベントスキーマを確認しての試行錯誤や、実際の検出結果が飛ぶまで動作確認しにくい部分があるのでぜひ本記事の内容を参考にしてもらえると嬉しいです。
通知先は、サンプル結果の通知先、AWSアカウント単位で振り分けた通知先、全てのイベントの通知先の3種類を作ります。 全てのイベントの通知先をわざわざ作るのは、万が一にもルールの設定ミスで通知を取りこぼさないためです。 セキュリティの脅威の通知という特性上セーフティな設計にしています。
サンプル結果の通知先
具体的なイベントパターンは次の通りです。
{
"source": ["aws.guardduty"],
"detail-type": ["GuardDuty Finding"],
"detail": {
"service": {
"additionalInfo": {
"value": [{
"wildcard": "*\"sample\":true*"
}]
}
}
}
}
サンプルであるかはドキュメントにもある通り additionalInfo の値から判定できます。 additionalInfo にはサンプルか否かの情報以外も入っている可能性があるのでワイルドカードで判定するというのがミソです。
アカウント単位の振り分け
具体的なイベントパターンは次のとおりです。
{
"source": ["aws.guardduty"],
"detail-type": ["GuardDuty Finding"],
"detail": {
"severity": [{
"numeric": [">=", 4]
}],
"accountId": ["xxxxxxxxxxxx", "xxxxxxxxxxxx", ・・・],
"service": {
"additionalInfo": {
"value": [{
"anything-but": {
"wildcard": "*\"sample\":true*"
}
}]
}
}
}
}
accountId に対象としたいAWSアカウントのIDを列挙してOR条件の一致判定で通知を振り分けます。 severity は必要に応じて指定してください。上記の例では Medium 以上の検出結果が通知されます。 また、こちらにはサンプルがひっかからないようにanything-butで除外します。
まとめ
本記事ではGuardDutyの通知について、弊社内の仕組みを紹介しました。
通知の設計は考慮すべき事が多くいつも悩ましい問題ですが、今回はセキュリティ脅威の通知という特性も考慮しつつ担当者にとってノイズにならない方向性を目指しました。 AWSアカウントの増加に伴って通知先を改善したように、今後も状況の変化に合わせて最適な方法を目指していきたいと思います。
We are Hiring!
エムスリーではSREを大募集中です。 もしSREの仕事に興味をお持ちいただけたなら、ぜひ以下のリンクから詳細をご確認ください。