Security HubのイベントをBedrockで翻訳してから通知してみた
2025年03月19日 水曜日

CONTENTS
はじめに
AWS Security Hubという、AWS環境のセキュリティの可視化と管理を一元化することが可能なサービスがあります。Security Hubでサポートされているセキュリティ基準に、作成したAWSリソースが引っかかった場合、Amazon SNSと連携すれば自身のメールアドレスに通知することが可能です。非常に便利なサービスなのですが、Security Hubのイベントの内容が、以下の画像のように英語なのがちょっと残念だなぁと思っていました。
内容は特段難しい英語ではないのでちょっと時間をかければ読めますし、急いでいるときは翻訳サイトを使えばいいです。ただ、Security Hubがイベントを発行する際、一気に複数件来ることとも少なくないため、それが全件英語で書かれていると、読まなきゃいけないとわかっていても読むのが億劫になってしまいます。
今回はそのような課題を解決すべく、Amazon Bedrockを使用し、Security Hubのイベントを翻訳してから通知するようにしてみたいと思います。
構成
AWS Step Functionsを使用してSecurity HubのAPIを叩いてイベントを取得し、Bedrockで翻訳してからSNSを通して通知を行います。以下からは、Step Functionsのワークフローの実装について記載していきます。
※Bedrockのモデルアクセスの有効化、SNSの作成は省略します。
実装
では、実際に構成図の内容を作っていきましょう。
Security Hub
まず、Security Hubを定義していきます。GetFindings APIを使用して、重要度が「High」か「Critical」、「AWS Foundational Security Best Practices」という基準に沿ったもの、というAPIパラメーターでSecurity Hubのイベントを取得します。
{ "Filters": { "SeverityLabel": [ { "Value": "HIGH", "Comparison": "EQUALS" }, { "Value": "CRITICAL", "Comparison": "EQUALS" } ], "ComplianceStatus": [ { "Value": "FAILED", "Comparison": "EQUALS" } ], "GeneratorId": [ { "Value": "aws-foundational-security-best-practices", "Comparison": "PREFIX" } ] }, "MaxResults": 1 }
Pass
取得したSecurity Hubのイベントからタイトルと説明、重要度を抜き出したかったので、ここでPass Stateを定義します。convoという名前の中に、タイトル、説明、重要度を入れて次のBedrockに渡します
{ "title.$": "$.Findings[0].Title", "convo.$": "States.Format('Title:{}\n Description:{}\n Severity:{}', $.Findings[0].Title, $.Findings[0].Description, $.Findings[0].Severity.Label)", }
Bedrock
BedrockのInvokeModel APIを使用し、回答生成を行います。使用するモデルはClaude Sonnet 3.5です。
System Promptでモデルにやってほしいこと、入力したデータの形式、出力形式を指定します。
{ "anthropic_version": "bedrock-2023-05-31", "max_tokens": 300, "system": "#目的 SecurityHubから抽出したデータを300文字以内でまとめ、セキュリティのレポートを作成しなさい。 #入力内容 Title=SecurityHubのアラートのタイトル Description=アラートの説明 Severity=アラートの重要度 #出力形式 タイトル:○○ 説明:○○", "messages": [ { "role": "user", "content": [ { "type": "text", "text.$": "States.Format('{}', $.convo)" } ] } ] }
SNS
SNSのPublish APIを使用します。事前に作成していたTopicのArnを指定しましょう。
Bedrockから出力された内容から、Bodyのtextだけ抜き出して通知したいと思います。
ワークフローの全体像
作成したワークフローは最終的にこんな感じになります。
{ "Comment": "A description of my state machine", "StartAt": "GetFindings", "States": { "GetFindings": { "Type": "Task", "Parameters": { "Filters": { "SeverityLabel": [ { "Value": "HIGH", "Comparison": "EQUALS" }, { "Value": "CRITICAL", "Comparison": "EQUALS" } ], "ComplianceStatus": [ { "Value": "FAILED", "Comparison": "EQUALS" } ], "GeneratorId": [ { "Value": "aws-foundational-security-best-practices", "Comparison": "PREFIX" } ] }, "MaxResults": 1 }, "Resource": "arn:aws:states:::aws-sdk:securityhub:getFindings", "Next": "Pass" }, "Pass": { "Type": "Pass", "Next": "Bedrock InvokeModel", "Parameters": { "title.$": "$.Findings[0].Title", "convo.$": "States.Format('Title:{}\n Description:{}\n Severity:{}', $.Findings[0].Title, $.Findings[0].Description, $.Findings[0].Severity.Label)" } }, "Bedrock InvokeModel": { "Type": "Task", "Resource": "arn:aws:states:::bedrock:invokeModel", "Parameters": { "ModelId": "arn:aws:bedrock:ap-northeast-1::foundation-model/anthropic.claude-3-5-sonnet-20240620-v1:0", "Body": { "anthropic_version": "bedrock-2023-05-31", "max_tokens": 300, "system": "#目的 以下のSecurityHubから抽出したデータを300文字以内でまとめ、セキュリティのレポートを作成しなさい #入力内容 Title=SecurityHubのアラートのタイトル Description=アラートの説明 Severity=アラートの重要度。#出力形式 テキスト形式で、タイトル:○○ 説明:○○で出力しなさい", "messages": [ { "role": "user", "content": [ { "type": "text", "text.$": "States.Format('{}', $.convo)" } ] } ] } }, "Next": "SNS Publish" }, "SNS Publish": { "Type": "Task", "Resource": "arn:aws:states:::sns:publish", "Parameters": { "Message.$": "$.Body.content[0].text", "TopicArn": "arn:aws:sns:ap-northeast-1:<アカウントID>:<トピック名>" }, "End": true } } }
実行
Step Functionsの実行ボタンを押して、イベントを起こしてみましょう。
まず、Security Hubから以下のような内容が検知されました。
{ "input": { "title": "ECR.1 ECR private repositories should have image scanning configured", "convo": "Title:ECR.1 ECR private repositories should have image scanning configured\n Description:This control checks whether a private ECR repository has image scanning configured. This control fails if a private ECR repository doesn’t have image scanning configured.\n Severity:HIGH" } }
そして、以下が実際に私のメールアドレスに通知された内容です
なかなかいいんじゃないでしょうか?
英語を日本語に訳しただけではありますが、すごく読みやすくなったように感じます。プロンプトを工夫すれば、もっと直感的に出来るかもしれません。
おわりに
Security Hubの内容をBedrockを用いて日本語化してから通知してみました。Bedrockはこういうちょっとした課題を解決するのに非常に便利なので重宝します。もし、この構成を自動化したい場合はAmazon EventBridgeでSecurity Hubのイベントを取得し、ターゲットをStep Functionsにすることで可能です。Security Hubやその他のセキュリティ系サービスの通知を意図した形に整形したい!という考えている方は、今回の構成をぜひ試してみてください。