S3バケットでのイベント通知の有効化について

このブログシリーズ 「クラウドセキュリティ 実践集」 では、一般的なセキュリティ課題を取り上げ、「なぜ危険なのか?」 というリスクの解説から、「どうやって直すのか?」 という具体的な修復手順(コンソール、AWS CLI、Terraformなど)まで、分かりやすく解説します。

今回は、Amazon S3バケットでイベント通知が有効になっていない状態について、そのリスクと対策を解説します。

ポリシーの説明

Amazon S3 の Security Hub コントロール – AWS Security Hub

[S3.11] S3 汎用バケットでは、イベント通知を有効にする必要があります

このコントロールは、S3 イベント通知が Amazon S3 汎用バケットで有効になっているかどうかをチェックします。バケットで S3 イベント通知が有効になっていない場合、コントロールは失敗します。eventTypes パラメータにカスタム値を指定したときは、指定されたタイプのイベントに対してイベント通知が有効になっている場合にのみコントロールが成功します。

リスク

Amazon S3は、データストレージ、静的ウェブサイトホスティング、データレイクなど、多岐にわたる用途で利用される非常に柔軟なサービスです。S3バケットでイベント通知が有効になっていない場合、バケット内で発生する重要な変更を見落とす可能性があり、以下のようなセキュリティおよび運用上のリスクが発生します。

  • 意図しないデータ変更の見落とし: S3バケット内のオブジェクトが意図せず作成、変更、または削除された際に、リアルタイムで検知できません。これは、設定ミス、不適切なスクリプト実行、または悪意のある行為によるデータ改ざんや損失につながる可能性があります。
  • セキュリティインシデント検知の遅延: 攻撃者がS3バケットに不正にアクセスし、マルウェアをアップロードしたり、機密データを削除したりした場合、イベント通知がなければ、インシデントの発生に気づくのが遅れ、被害が拡大する可能性があります。

対策

S3バケットのイベント通知を有効にすることは、S3バケット内で発生するオブジェクト操作をリアルタイムで監視し、それに対応するアクションを自動化するための重要なベストプラクティスです。

  • 通知イベントの選択: 監視したい特定のS3イベントタイプを選択します。一般的なイベントタイプには以下があります。
    • s3:ObjectCreated:*(オブジェクトの作成)
    • s3:ObjectRemoved:*(オブジェクトの削除)
    • s3:ObjectRestore:*(オブジェクトの復元)
    • s3:ReducedRedundancyLostObject(Reduced Redundancy Storageでオブジェクトが失われた場合)
  • 通知の送信先 (宛先): S3イベント通知の送信先として、以下のいずれかを選択します。
    • Amazon SNS トピック: 複数のサブスクライバー(メール、SMS、Lambda関数、SQSキューなど)に通知を配信できます。
    • Amazon SQS キュー: イベントをキューに格納し、非同期的に処理できます。
    • AWS Lambda 関数: イベントが発生したときにコードを自動的に実行し、カスタムロジックを適用できます。
  • フィルタリングの設定: 必要に応じて、オブジェクトのプレフィックス(フォルダパス)やサフィックス(ファイル拡張子)に基づいてイベントをフィルタリングすることで、特定のオブジェクトのみのイベントを通知できます。これにより、不要な通知を減らし、関連するイベントのみに焦点を当てることができます。
  • IAM権限の確認: S3が通知を送信するための適切なIAM権限を持っていることを確認してください。SNSトピック、SQSキュー、またはLambda関数に、S3からのs3:PutEventアクションを許可するリソースベースのポリシーが必要です。
  • 監視と対応: イベント通知がトリガーされた際には、関連チームにアラートを送信したり、自動的な対処(例: 削除されたオブジェクトのリカバリ試行、不審なアップロードのブロック)を実行したりするメカニズムを構築します。

修復方法

AWSコンソールでの修復手順

AWSコンソールを使用して、S3バケットのイベント通知を設定します。

前提:

  • イベント通知を設定したいS3バケットが存在すること。
  • 通知の送信先となるSNSトピック、SQSキュー、またはLambda関数が既に存在すること。
  1. S3サービスへ移動: AWSコンソールにログインし、Amazon S3 サービスを開きます。
  2. 対象のS3バケットを選択: イベント通知を設定したいS3バケットを選択します。
  3. プロパティタブへ移動: バケットの詳細ページで、「プロパティ」タブをクリックします。
  4. イベント通知の設定:イベント通知」セクションを見つけ、「イベント通知を作成」をクリックします。
  1. イベント通知の詳細設定:
    • イベント通知名: 任意の名前を付けます(例: ObjectCreationNotification)。
    • プレフィックス (オプション): イベント通知を特定のフォルダ内のオブジェクトに限定したい場合は、プレフィックス(例: uploads/)を指定します。
    • サフィックス (オプション): イベント通知を特定のファイル拡張子に限定したい場合は、サフィックス(例: .jpg)を指定します。
    • イベントタイプ: 監視したいイベントタイプを1つ以上選択します。例えば、「すべてのオブジェクト作成イベント」(All object create events) や、「すべてのオブジェクト削除イベント」(All object delete events) など。
    • 送信先: ドロップダウンメニューから以下のいずれかを選択します。
      • SNS トピック: 既存のトピックを選択するか、新しいトピックを作成します。
      • SQS キュー: 既存のキューを選択するか、新しいキューを作成します。
      • Lambda 関数: 既存の関数を選択します。
    • 選択した送信先に応じて、該当するARNまたは名前を入力または選択します。
  2. 変更を保存: 設定を確認し、「変更を保存」をクリックします。

これにより、指定したS3バケットで、選択されたイベントタイプが発生した際に、設定した宛先に通知が送信されるようになります。

Terraformでの修復手順

TerraformでS3バケットのイベント通知を有効にするには、aws_s3_bucket_notification リソースを使用します。このリソースは、S3バケットの通知設定を管理します。

# (例) イベント通知を設定するS3バケット
resource "aws_s3_bucket" "my_event_bucket" {
  bucket = "my-s3-event-bucket-unique-20250706" # グローバルで一意の名前に変更
  acl    = "private"

  tags = {
    Name = "MyEventNotificationBucket"
  }
}

# (例) イベント通知の送信先となるSNSトピック
resource "aws_sns_topic" "s3_event_topic" {
  name = "s3-object-change-notification"
  tags = {
    Environment = "Production"
  }
}

# SNSトピックにS3からの Publish 権限を付与するポリシー
resource "aws_sns_topic_policy" "s3_topic_policy" {
  arn    = aws_sns_topic.s3_event_topic.arn
  policy = jsonencode({
    Version = "2012-10-17",
    Statement = [
      {
        Effect    = "Allow",
        Principal = {
          Service = "s3.amazonaws.com"
        },
        Action    = "sns:Publish",
        Resource  = aws_sns_topic.s3_event_topic.arn,
        Condition = {
          ArnLike = {
            "aws:SourceArn" = aws_s3_bucket.my_event_bucket.arn
          }
        }
      }
    ]
  })
}

# (オプション) SNSトピックの購読者 (メールアドレスなど)
resource "aws_sns_topic_subscription" "s3_event_email_subscription" {
  topic_arn = aws_sns_topic.s3_event_topic.arn
  protocol  = "email"
  endpoint  = "your-security-team@example.com" # 通知を受け取るメールアドレスに置き換え
  # `confirmation_timeout_in_minutes` は、Lambdaなど自動承認されるプロトコルで有効
  # emailプロトコルの場合、手動で承認が必要
}

# S3バケットのイベント通知設定
resource "aws_s3_bucket_notification" "bucket_notifications" {
  bucket = aws_s3_bucket.my_event_bucket.id

  # オブジェクト作成イベントの通知
  topic_filter {
    id = "object_created_notification"
    topic_arn = aws_sns_topic.s3_event_topic.arn
    events    = ["s3:ObjectCreated:*"] # すべてのオブジェクト作成イベント
    
    # 必要に応じてフィルタリング
    # filter_prefix = "uploads/"
    # filter_suffix = ".txt"
  }

  # オブジェクト削除イベントの通知
  topic_filter {
    id = "object_removed_notification"
    topic_arn = aws_sns_topic.s3_event_topic.arn
    events    = ["s3:ObjectRemoved:*"] # すべてのオブジェクト削除イベント
  }

  # (オプション) Lambda関数への通知の例
  /*
  lambda_function {
    id            = "process_new_image"
    lambda_function_arn = aws_lambda_function.image_processor.arn
    events        = ["s3:ObjectCreated:Put"]
    filter_prefix = "images/"
  }

  # (オプション) SQSキューへの通知の例
  sqs_queue {
    id        = "data_ingestion_queue"
    queue_arn = aws_sqs_queue.data_queue.arn
    events    = ["s3:ObjectCreated:*"]
  }
  */
}

# (オプション) Lambda関数やSQSキューを通知先に使う場合の例
/*
resource "aws_lambda_function" "image_processor" {
  # ... Lambda関数の定義 ...
}

resource "aws_lambda_permission" "allow_s3_to_call_lambda" {
  statement_id  = "AllowExecutionFromS3Bucket"
  action        = "lambda:InvokeFunction"
  function_name = aws_lambda_function.image_processor.function_name
  principal     = "s3.amazonaws.com"
  source_arn    = aws_s3_bucket.my_event_bucket.arn
}

resource "aws_sqs_queue" "data_queue" {
  name = "my-data-ingestion-queue"
  # ... SQSキューの定義 ...
}

resource "aws_sqs_queue_policy" "sqs_policy_for_s3" {
  queue_url = aws_sqs_queue.data_queue.id
  policy = jsonencode({
    Version = "2012-10-17",
    Statement = [
      {
        Effect = "Allow",
        Principal = {
          Service = "s3.amazonaws.com"
        },
        Action = "sqs:SendMessage",
        Resource = aws_sqs_queue.data_queue.arn,
        Condition = {
          ArnLike = {
            "aws:SourceArn" = aws_s3_bucket.my_event_bucket.arn
          }
        }
      }
    ]
  })
}
*/

上記のTerraformコードでは、aws_s3_bucket_notification リソースを使用してS3バケットのイベント通知を設定しています。

  • bucket: イベント通知を設定するS3バケットのIDを指定します。
  • topic_filterlambda_functionsqs_queue ブロックを使用して、それぞれの宛先タイプとイベントタイプを定義します。
  • events: 監視したいイベントタイプ(例: "s3:ObjectCreated:*""s3:ObjectRemoved:*" など)を指定します。
  • filter_prefixfilter_suffix: オプションで、特定のオブジェクトパスやファイル拡張子にイベントをフィルタリングできます。

重要な注意点: S3がSNSトピック、SQSキュー、またはLambda関数にイベントを送信するためには、それらのリソースに対する適切なIAM権限が必要です。Terraformコードでは、aws_sns_topic_policy でS3からのPublishを許可する例を示しています。Lambda関数やSQSキューを宛先にする場合も、同様にリソースベースのポリシーを設定する必要があります。

my-s3-event-bucket-unique-20250706your-security-team@example.com などのプレースホルダーは、実際の環境に合わせて修正してください。

最後に

この記事では、S3バケットのイベント通知を有効にすることの重要性について解説しました。S3イベント通知は、データ変更の迅速な検知、セキュリティインシデントへの対応、コンプライアンス要件の達成、および自動化されたデータ処理ワークフローのトリガーとして、AWS環境におけるデータガバナンスとセキュリティを強化するための非常に強力なツールです。 貴社のS3バケットでは、重要なイベントに対する通知が適切に設定されていますか?この機会にぜひ設定を確認・強化してみてください。 こちらの内容の検出は弊社が提供するSecurifyのCSPM機能で簡単に検出及び管理する事が可能です。運用が非常にラクに出来る製品になっていますのでぜひ興味がある方はお問い合わせお待ちしております。

最後までお読みいただきありがとうございました。この記事が皆さんの役に立てば幸いです。

この記事をシェアする

クラウドセキュリティ対策実践集一覧へ戻る

貴社の利用状況に合わせた見積もりを作成します。

料金プランを詳しく見る