情報システム部でAWS周りの運用保守をしている「ねぎ」です、こんにちは!
AWSの各種サービスから通知を受ける際には何を使っているでしょうか?
メールでしょうか?Slackでしょうか?それともまた別のものをご利用でしょうか?
今回の記事では、
- 重要な通知にはSlackを使いたいけど、Chatbotではアカウント名が表示されずにわかりにくい
Chatbotではアカウント名が表示出来ない(2022年10月15日確認時)ため、運用するAWSアカウント数が増えれば増えるほど、アカウントIDから判断するのが大変!
といった、かゆいところに手が届いてない方向けに情報を発信していきたいと思います。
Chatbotを使ってSlack通知をしてみた
Chatbotを活用したChatOpsという記事もAWSさんが以下のように書かれています。
さっそく試しにChatbotを使ってSlack通知してみます
重要度が高い通知については、「赤色」になっていたり非常にわかりやすいと思います。
(本来であればアカウントIDが表示されているところは、マスキングさせてもらっています)
ただ1点、アカウント名が表示されていないですよね。
Slackで通知されるアカウントIDからアカウント名を答えられるように、全てのアカウントIDとアカウント名の紐づきを覚えればいいじゃないか、ごもっともです........。
ただ私は100アカウント近くなっているアカウントIDを全て覚えて、、、
Slack通知されたアカウントIDからアカウント名をすぐに回答するだけの脳みそがなく、、、
一部のチームからもSlack通知時にアカウント名表示をして欲しい、、、
という改善要望もあったので、Slack通知時にアカウント名を表示させたいと思うようになりました。
やり方を考えてみる
Chatbotではアカウント名を表示させることが出来ないことを確認しています。(2022年10月15日時点)
すごく手軽に設定が出来て良いサービスなのですが、断念せざるを得ない状況です。
次に良くありそうな、lambda + Slack(Webhook URL)の仕組みで通知が出来ないか検討をしてみました。
この構成なら出来そうだな、と思いながら色々と大変なポイントがあったので、この後紹介をしていきたいと思います。
JSONを考える
Slackに通知するAWSサービスの対象として、弥生では「GuardDuty」、「SecurityHub」を対象としています。
今回は「GuardDuty」についてSlack通知するためのJSONを考えてみようと思います。
「GuardDuty」のJSON形式の例としては以下のような記事があります。
通知テストのためのGuardDuty Findingsのjsonサンプル置いておきます | DevelopersIO
上記の記事で紹介されていたGuardDutyで検知された際に出力されるJSONの各情報から、必要なものをSlackの通知フォーマットへ合わせる必要があります。
Slackへ通知する際のフォーマットは以下で紹介されています。
Reference: Secondary message attachments | Slack
これだけではわかりにくいと思いますので、ざっくりまとめると以下のようになります。
{ "attachments": [ { “color”: 重要度に応じた色, “title”: 重要度に応じた絵文字 + “GuardDuty Finding | ” + リージョン + “ | Account: “ + アカウントID", “title_link”: “https://リージョン.console.aws.amazon.com/guardduty/home?region=リージョン#/findings?search=id%3検出結果ID¯os=current", “text”: 検出結果タイプ \n 検出結果説明, "fields": [ { “title”: “First Seen”, “value”: 初回検出日時, "short": True }, { “title”: “Last Seen”, “value”: 最終検出日時, "short": True }, { “title”: “Severity”, “value”:重要度, "short": True }, { “title”: “Thread Count”, 検出回数, "short": True } ], } ] }
このJSONの形式が決まると、SlackへChatbotのように成形された通知が送信出来るようになります。
アカウント名取得するには
ここまででChatbotに近い形式で通知が行えるようにするSlackのJSONフォーマットが決まりました。
ただ元々の問題だった、「アカウント名の取得」が解決出来ていません。
この問題を解決するには、lambdaで以下の記述をすることでアカウント名を取得することが可能です。
boto3.client(organizatinos).describe_account(AccountID)
これでアカウント名を表示させて、Slackへの通知が可能だ!、と浮かれていましたが壁が立ちはだかりました。。。。
弥生では「ControlTower」というAWSのサービスを使用して、マルチアカウント環境を構築しています。
GuardDutyの検知情報は「Audit」というアカウントに集約させています。
しかし、アカウント名取得するためには「Master Account」でlambdaのコマンドを発行する必要がありました。
つまりアーキテクチャとしては以下のようになります。
「Audit」アカウントに集約したGuardDutyの検知情報をEventBridgeで拾い、EventBridgeイベントバスを使って、「Master Account」のEventBridgeへ連携させます。
そのまま「Master Account」のlambda関数でアカウントIDからアカウント名を取得し、GuardDutyのJSONをSlack通知フォーマットへ合わせて通知する、といった流れになります。
単に「GuardDutyをSlackへ通知したい」だけなのに、2つのアカウントを使って実装しなければならない、、、なんか仰々しくないでしょうか?
え?そんなことない??
私はこれが嫌でさらにアーキテクチャを検討することにしました。
アーキテクチャを簡単にする
アーキテクチャを簡単にしたい!ということで、壁にぶちあたりましたが、AWSの機能アップデートで良さそうなものを見つけました。
AWS Organizations で委任管理者機能をリリース
AWS Organizationsの一部権限を委譲出来るというものです。
これで「Audit」アカウントに必要な権限を委譲することで、簡単に出来ると思いました。
権限移譲を試してみた結果、以下のようなアーキテクチャで実現することが可能となりました!
え?あまり変わってないw?
元のアーキテクチャと良く見比べてみてください!
私としてはアカウントを跨がずに実現が出来るようになった、という点がすごく良かったと思っています。
あとがき
AWSは便利で良く活用をさせてもらってますが、それでも自社の環境下で使うには、「ここがイマイチ」という部分もあるかと思います。
色々なサービスを組み合わせれば、実現不可能なものは少ないとも思いますが、そのために複雑なアーキテクチャにしてしまっては運用保守が大変だと思っています。
運用保守を楽にしていくためにも、アーキテクチャを簡易なものにしていく、そのために各AWSサービスをうまく活用してみたり、各機能のアップデートをチェックして、活用できるものがあれば取り入れて改修をする、といったことも重要なんだな、と感じた対応でした。