Cloud One File Storage Security拡張編:Amazon S3のマルウェアファイル検出時にメール通知を行う

AWS

2024.3.12

Topics

はじめに

こんにちは、Shunです。

今回は、Cloud One File Storage Security(以降、C1FSS)を使用して、S3のマルウェアファイル検出時にメール通知を行う方法をご紹介します。

Trend Micro Cloud One™ – File Storage Security は、 Amazon Web Services (AWS) Azureや GCPなどのクラウド ストレージ サービス内のファイルに対するマルウェア対策スキャンを提供します。

以下の記事でアップロードされたファイルのマルウェアを検知する方法をご紹介しました。

関連記事
Cloud One File Storage Securityを活用したAmazon S3マルウェアスキャンの手順

しかし、これまでのセットアップでは以下の構成の通り、アップロードされたファイルがマルウェアと判断された場合、ユーザーへの通知は行われませんでした。

このため、異常なファイルがS3に残され、他のユーザーによってダウンロードされると、マルウェアが拡散するリスクが生じます。

今回はマルウェアが検出された際に迅速に対応できるよう、メール通知機能を追加する方法を解説します。

Slack通知の設定については別の記事で詳しく説明しています。

関連記事
Cloud One File Storage Security拡張編:Amazon 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_idemail及び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にアップロードされた際に即座に警告を受け取ることができます。

他の追加機能については、以下の記事でご紹介しています。

関連記事
Cloud One File Storage Security拡張編:Amazon S3の既存データのマルウェアチェックを行う

関連記事
Cloud One File Storage Security拡張編:Amazon S3のマルウェアファイルを自動で振り分ける

関連記事
Cloud One File Storage Security拡張編:Amazon S3のマルウェアファイル検出時にSlack通知を行う

最後まで読んでいただきありがとうございます!

Shun

好きな言葉は生ビール199円です。日本ビール協会認定1冠、AWS12冠、Google Cloud11冠

Recommends

こちらもおすすめ

Special Topics

注目記事はこちら