Cloud One File Storage Security拡張編:Amazon S3のマルウェアファイル検出時にメール通知を行う
はじめに
こんにちは、Shunです。
今回は、Cloud One File Storage Security(以降、C1FSS)を使用して、S3のマルウェアファイル検出時にメール通知を行う方法をご紹介します。
Trend Micro Cloud One™ – File Storage Security は、 Amazon Web Services (AWS) Azureや GCPなどのクラウド ストレージ サービス内のファイルに対するマルウェア対策スキャンを提供します。
以下の記事でアップロードされたファイルのマルウェアを検知する方法をご紹介しました。
しかし、これまでのセットアップでは以下の構成の通り、アップロードされたファイルがマルウェアと判断された場合、ユーザーへの通知は行われませんでした。
このため、異常なファイルがS3に残され、他のユーザーによってダウンロードされると、マルウェアが拡散するリスクが生じます。
今回はマルウェアが検出された際に迅速に対応できるよう、メール通知機能を追加する方法を解説します。
Slack通知の設定については別の記事で詳しく説明しています。
メール通知の設定は、公式ドキュメント「Post Scan Action – Email Notification」を参考にしています。
公式ドキュメント:Post Scan Action – Email Notification
ただし、ここではSESではなく、SNSを使用してメール通知を行います。
前提
- Terraformのセットアップが完了していること
- C1FSSのセットアップが完了していること
構成図
以下の構成図では、赤枠で囲まれた箇所が今回追加で構築する箇所です。
実装
今回は、Terraformを用いて実装を行います。
ディレクトリ構成
以下は今回のディレクトリ構成です。
├─ provider.tf ├─ lambda.tf ├─ sns.tf └─ lambda └─ handler.py
provider.tf
locals
内のaws_id
、email
及びbackend
を適切なものへ書き換えてください。
locals { aws_id = "xxxxx" email = "xxxxx" } terraform { backend "s3" { key = "xxxx/terraform.tfstate" bucket = "xxxxxx" dynamodb_table = "xxxxxxx" region = "ap-northeast-1" } required_providers { aws = { source = "hashicorp/aws" version = "~> 5.0" } } }
lambda.tf
lambda.tf
では、SNSへ通知する権限の付与やメール整形用のPythonファイルの指定を行っています。
function_name
を適宜書き換えてください。
data "archive_file" "email" { type = "zip" source_dir = "./lambda" output_path = "./lambda/handler.zip" } resource "aws_lambda_function" "email" { function_name = "xxxxxx" handler = "handler.lambda_handler" runtime = "python3.12" filename = data.archive_file.email.output_path source_code_hash = data.archive_file.email.output_base64sha256 role = aws_iam_role.lambda_role.arn environment { variables = { SNS_TOPIC_ARN = aws_sns_topic.email.arn } } } resource "aws_lambda_permission" "email" { statement_id = "AllowExecutionFromSNS" action = "lambda:InvokeFunction" function_name = aws_lambda_function.email.function_name principal = "sns.amazonaws.com" source_arn = data.aws_sns_topic.c1fss.arn } resource "aws_iam_role" "lambda_role" { name = "example-lambda-role" assume_role_policy = <<EOF { "Version": "2012-10-17", "Statement": [ { "Action": "sts:AssumeRole", "Principal": { "Service": "lambda.amazonaws.com" }, "Effect": "Allow", "Sid": "" } ] } EOF managed_policy_arns = [ "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", aws_iam_policy.lambda_sns_publish.arn ] } resource "aws_iam_policy" "lambda_sns_publish" { name = "lambda_sns_publish" path = "/" policy = jsonencode({ Version = "2012-10-17" Statement = [ { Effect = "Allow" Action = "sns:Publish" Resource = [aws_sns_topic.email.arn] }, ] }) }
sns.tf
sns.tf
では、C1FSSのセットアップ時のScanResultTopicARN
を取得します。(1行目)
ScanResultTopicARN
をトリガーにLambdaが実行されます。
name
に関しては、適宜書き換えてください。
data "aws_sns_topic" "c1fss" { name = "xxxxx" } resource "aws_sns_topic" "email" { name = "xxxxx" } resource "aws_sns_topic_policy" "email" { arn = aws_sns_topic.email.arn policy = <<POLICY { "Version": "2008-10-17", "Id": "__default_policy_ID", "Statement": [ { "Sid": "__default_statement_ID", "Effect": "Allow", "Principal": { "AWS": "*" }, "Action": [ "SNS:Publish", "SNS:RemovePermission", "SNS:SetTopicAttributes", "SNS:DeleteTopic", "SNS:ListSubscriptionsByTopic", "SNS:GetTopicAttributes", "SNS:AddPermission", "SNS:Subscribe" ], "Resource": "${aws_sns_topic.email.arn}", "Condition": { "StringEquals": { "AWS:SourceOwner": ${local.aws_id} } } }, { "Sid": "", "Effect": "Allow", "Principal": { "Service": "lambda.amazonaws.com" }, "Action": "sns:Publish", "Resource": "${aws_sns_topic.email.arn}" } ] } POLICY } resource "aws_sns_topic_subscription" "email" { topic_arn = aws_sns_topic.email.arn protocol = "email" endpoint = local.email }
handler.py
Trend Microが公式で提供しているPythonでは、SESを使用しているのですが、今回はSNSを使用してメール通知を行います。
参考:cloudone-filestorage-plugins/post-scan-actions/aws-python-email-notification
/handler.py
メールへの通知文をハイライト箇所で定義しています。
本文を変更したい方は、カスタマイズして使ってみてください。
import json import os import boto3 from botocore.exceptions import ClientError def lambda_handler(event, context): sns_topic_arn = os.environ['SNS_TOPIC_ARN'] aws_region = os.environ['AWS_REGION'] sns_client = boto3.client('sns', region_name=aws_region) for record in event['Records']: message = json.loads(record['Sns']['Message']) findings = message['scanning_result'].get('Findings') if findings: email_content = "CloudOne FSS Notification - Malware Detected\n\n" email_content += "File URL: {}\n\n".format(message['file_url']) for finding in findings: email_content += "Malware: {}\nType: {}\n\n".format( finding.get('malware'), finding.get('type')) try: response = sns_client.publish( TopicArn=sns_topic_arn, Message=email_content, Subject='CloudOne FSS Alert' ) except ClientError as e: print(json.dumps(e.response['Error']['Message'])) return else: print("Notification sent! Message ID: " + response['MessageId']) return print("No findings to report.")
さいごに
今回、ご紹介したTerraformを実装することで、異常なファイルがS3にアップロードされた際に即座に警告を受け取ることができます。
他の追加機能については、以下の記事でご紹介しています。
最後まで読んでいただきありがとうございます!
テックブログ新着情報のほか、AWSやGoogle Cloudに関するお役立ち情報を配信中!
Follow @twitterGoogle Cloud Partner Top Engineer 2025、2024 AWS All Cert、ビール検定1冠
Recommends
こちらもおすすめ
Special Topics
注目記事はこちら
データ分析入門
これから始めるBigQuery基礎知識
2024.02.28
AWSの料金が 10 %割引になる!
『AWSの請求代行リセールサービス』
2024.07.16