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


