AWS

生成AIを用いてセキュリティアラートをカスタマイズする

hisadon

はじめに

こんにちは。hisadonです。
今回は Amazon GuardDuty のセキュリティアラートを生成AIを用いて、良い感じにメールを送信するナレッジをご紹介したいと思います。

実装の推しポイント

  1. 検知したセキュリティアラートの原因と対策を生成AIに出してもらいました。

実装後に届くメールイメージ

AWS構成イメージ

Amazon GuardDutyとは?

Amazon GuardDutyは、AWSのセキュリティサービスでリアルタイムで脅威検出を行うツールです。

  1. 脅威検出:GuardDutyは、VPCフローログ、AWS CloudTrail管理イベントログ、DNSログなどのデータソースを利用して、異常な活動や不正アクセスを検出します。これにより、サイバー攻撃や内部不正の兆候を見逃さずに把握することができます。
  2. 自動解析:機械学習や統計分析を用いて、膨大なデータから潜在的な脅威を自動的に抽出します。これにより、セキュリティ担当者が効率的に対策を講じることが可能です。
  3. 警告と通知:GuardDutyは、脅威を検出するとアラートを生成し、AWSマネジメントコンソールやメール、SNS、サードパーティ製品などを通じて通知します。これにより、迅速に対応を行うことができます。
  4. 継続的な監視:常にAWS環境を監視し続けるため、新しい脅威が発生した場合にもすぐに対応できます。クラウド環境のセキュリティを強化し、リスクを最小限に抑えることができます。

実装に向けての前提

  • 東京リージョンにて実装する
  • AWS CloudShellのコマンドを用いて実装する

実装の流れ

  1. Amazon GuardDutyを有効化する。
  2. Amazon SES で連絡先メールアドレスを登録する。
  3. Amazon Bedrockを利用できる様にする
  4. AWS Lambda の関数を作成する。
  5. Amazon EventBridge で Amazon GuardDuty の通知を拾う設定を投入する。
  6. AWS CloudShell にてテストアラートを作成する。

設定手順1(Amazon GuardDutyを有効化する)

1.AWS CloudShell を起動して、以下のコマンドを実施します。

$ aws guardduty create-detector --enable --region ap-northeast-1

設定手順2(Amazon SESで連絡先メールアドレスを登録する)

1.AWS CloudShell を起動して、以下のコマンドを実施します。
※ "your-email@example.com" は受信したいメールアドレスに直してください

$ aws ses verify-email-identity --email-address "your-email@example.com" --region ap-northeast-1

2.AWSから検証メールが届きますので、URLをクリックします。(Amazon SESの設定は完了)

設定手順3(Amazon Bedrockを利用できる様にする)

1.東京リージョンが選択されている状態で、Amazon Bedrockを選択し下記のような画面に遷移することを確認します。

2.画面内にある「モデルアクセスをリクエスト」を選択します。

3.ステータスが「リクエスト可能」との表示の場合、Bedrockが使えていない状態です。「リクエスト可能」を選択し、モデルアクセスをリクエストしましょう。
※ 参考ですが各リージョンで使えるベースモデルは異なり、北米のリージョンだと表示よりも多くのベースモデルが利用可能です。

4.今回はAnthropicのClaudeが利用可能であれば問題ありません。一旦は全て選択して利用可能な様にしていきます。トしましょう。
※ Anthropicだけは「ユースケースの詳細」を入力する必要があります。画面フォームに従い会社名などを入力して送信します。

5.以下のような画面になっていたら利用可能な状態です。

設定手順4(AWS Lambda の関数を作成する)

1.AWS GUI 上で東京リージョンを選択する。
2.AWS Lambdba を選択する。
3.関数の作成を実施し、以下を指定します。
- オプション:一から作成
- 関数名:自由につけちゃってOK
- ランタイム:Python 3.12
- 他はそのままで「関数の作成」でOK

4.以下のPythonコードを記述します。
※ コード内で変更が必要な箇所はありません。

import json
import boto3
import os

# SESとBedrockのクライアントを作成
ses_client = boto3.client('ses')
bedrock_client = boto3.client('bedrock-runtime')  # 正しいクライアント名を使用してください

# 環境変数からSES送信元と送信先のメールアドレスを取得
SES_SENDER_EMAIL = os.environ['SES_SENDER_EMAIL']
SES_RECIPIENT_EMAIL = os.environ['SES_RECIPIENT_EMAIL']

def lambda_handler(event, context):
    # イベントがリストとして渡される場合の処理
    if isinstance(event, list):
        event = event[0]
    
    # イベントが辞書であることを確認
    if not isinstance(event, dict):
        return {'statusCode': 400, 'body': json.dumps('Invalid event format')}

    # イベントから詳細を取得
    detail = event.get('detail', {})

    # 解析する情報を抽出
    account_id = event.get('account', '不明')
    region = event.get('region', '不明')
    severity = detail.get('severity', '不明')
    finding_id = detail.get('id', '不明')
    finding_type = detail.get('type', '不明')
    resource_type = detail.get('resource', {}).get('resourceType', '不明')

    # 解析リクエストメッセージを生成
    prompt = (
        f'AWS GuardDuty 検知結果\n'
        f'アカウントID: {account_id}\n'
        f'リージョン: {region}\n'
        f'重要度: {severity}\n'
        f'検出結果ID: {finding_id}\n'
        f'検出結果タイプ: {finding_type}\n'
        f'影響を受けるリソース: {resource_type}\n'
        f'原因と対策を教えてください。\n'
    )

    try:
        # Bedrock APIを呼び出し
        response = bedrock_client.invoke_model(
            modelId='anthropic.claude-v2:1',
            contentType='application/json',
            accept='application/json',
            body=json.dumps({
                "prompt": f"Human: {prompt}\nAssistant:",
                "max_tokens_to_sample": 500,
                "temperature": 0.7
            })
        )
        # 非同期でレスポンスを待つ
        response_body = response['body'].read().decode('utf-8')
        analysis_result = json.loads(response_body).get('completion', '分析結果が返されませんでした。')
    except Exception as e:
        analysis_result = f"GuardDutyイベントの処理中にエラーが発生しました: {str(e)}"

    # SESを使用してメールを送信
    try:
        ses_client.send_email(
            Source=SES_SENDER_EMAIL,
            Destination={'ToAddresses': [SES_RECIPIENT_EMAIL]},
            Message={
                'Subject': {'Data': "GuardDuty Event Analysis Result", 'Charset': 'UTF-8'},
                'Body': {'Text': {'Data': f"Analysis Result:\n\n{prompt}\n\n{analysis_result}", 'Charset': 'UTF-8'}}
            }
        )
    except Exception as e:
        return {'statusCode': 500, 'body': json.dumps(f"メール送信中にエラーが発生しました: {str(e)}")}

    return {'statusCode': 200, 'body': json.dumps('Email sent successfully!')}

5.AWS CloudShell にて以下のコマンドを実施し、環境変数に値を設定します。
※ "function-name"は、作成したAWS Lambdaの関数名に直してください。
※ "your-email@example.com"は、手順内で作成したAmazon SESに設定したメールアドレスに直してください。

$ aws lambda update-function-configuration \
    --function-name "function-name" \
    --environment "Variables={ \
        SES_RECIPIENT_EMAIL="your-email@example.com", \
        SES_SENDER_EMAIL="your-email@example.com" \
    }"

6.AWS CloudShell にて以下のコマンドを実施し、AWS Lambd のIAMロールを修正します。
※ "Lambdaに適用されているロール名" の箇所は適宜修正してください。

$ aws iam put-role-policy \
    --role-name "Lambdaに適用されているロール名" \
    --policy-name BedrockAccessPolicy \
    --policy-document '{
        "Version": "2012-10-17",
        "Statement": [
            {
                "Effect": "Allow",
                "Action": [
                    "bedrock:InvokeModel"
                ],
                "Resource": "*"
            },
            {
                "Effect": "Allow",
                "Action": [
                    "ses:SendEmail",
                    "ses:SendRawEmail"
                ],
                "Resource": "*"
            }
        ]
    }'

7.AWS CloudShell にて以下のコマンドを実施し、AWS Lambda のタイムアウトを15秒に変更しておきます。
※ "function-name" はLambdaの関数名に直してください。

$ aws lambda update-function-configuration --function-name <function-name> --timeout 15

設定手順5(Amazon EventBridge で Amazon GuardDuty の通知を拾う設定を投入する)

1.AWS CloudShell にて以下のコマンドを実施し、Amazon EventBridgeルールを作成します。
※ コマンド内で変更が必要な箇所はありません。

aws events put-rule \
    --name GuardDutyAllFindingsRule \
    --event-pattern '{
        "source": ["aws.guardduty"],
        "detail-type": ["GuardDuty Finding"]
    }' \
    --description "Rule to catch all GuardDuty findings" \
    --region ap-northeast-1

2.AWS CloudShell にて以下のコマンドを実施し、作成したLambdaのARNを取得します。
※ "function-name"は、作成したLambdaの関数名に直してください。

$ export LAMBDA_ARN=$(aws lambda get-function --function-name "function-name" --query 'Configuration.FunctionArn' --output text)
$ echo $LAMBDA_ARN

3.AWS CloudShell にて以下のコマンドを実施し、Amazon EventBridgeにてターゲットを指定します。
※ コマンド内で変更が必要な箇所はありません。

aws events put-targets \
    --rule GuardDutyAllFindingsRule \
    --targets "[
        {
            \"Id\": \"1\",
            \"Arn\": \"${LAMBDA_ARN}\"
        }
    ]" \
    --region ap-northeast-1

設定手順6(AWS CloudShell にてテストアラートを作成する)

1.AWS CloudShell にて以下のコマンドを実施し、Amazon Guardduty のデテクターIDを取得する。

$ DETECTOR_ID=$(aws guardduty list-detectors --query 'DetectorIds[0]' --output text)
$ echo $DETECTOR_ID

2.テストデータを生成する。

$ aws guardduty create-sample-findings --detector-id $DETECTOR_ID --finding-types "Backdoor:EC2/DenialOfService.Dns"

3.意図したセキュリティメールが届いているか確認する。

まとめ

Amazon GuardDutyと生成AIの組み合わせにより、原因と対策を出力させてみました。
これにより検知時の初動も早くなり、セキュリティリスクをより軽減できるかと思います。
この記事が皆様のセキュリティ対応に役立つことを願っています。

AUTHOR
hisadon
hisadon
記事URLをコピーしました