S3バケットのオブジェクトレベルの書き込みログの有効化設定手順

このブログシリーズ 「クラウドセキュリティ 実践集」 では、一般的なセキュリティ課題を取り上げ、「なぜ危険なのか?」 というリスクの解説から、「どうやって直すのか?」 という具体的な修復手順(コンソール、AWS CLI、Terraformなど)まで、分かりやすく解説します。
この記事では、Amazon S3バケットで オブジェクトレベルの書き込みイベントのログ記録 が有効になっていない状態について、そのリスクと対策を解説します。

ポリシーの説明
Amazon S3 の Security Hub コントロール – AWS Security Hub
このコントロール AWS アカウント は、 に Amazon S3 バケットのすべての書き込みデータイベントを記録する AWS CloudTrail マルチリージョン証跡が少なくとも 1 つあるかどうかをチェックします。 Amazon S3 S3 バケットの書き込みデータイベントをログに記録するマルチリージョン証跡がアカウントに存在しない場合、コントロールは失敗します。
リスク
Amazon S3は、多くの企業にとって重要なデータレイクやストレージ基盤として利用されています。S3バケットへのオブジェクトの書き込み(新規作成、上書き、削除など)は、データに対する重要な変更操作であり、これらのイベントを詳細に監視することは、セキュリティとコンプライアンスの観点から非常に重要です。オブジェクトレベルの書き込みイベントのログ記録が有効になっていない場合、以下のようなリスクが発生します。
- 不正なデータ変更・削除の検知遅延: 誰が、いつ、どのS3オブジェクトを書き込んだり、変更したり、削除したりしたかという情報が記録されないため、不正なデータ操作があった場合に、その事実を即座に検知することが困難になります。これにより、被害の拡大を防ぐための初期対応が遅れる可能性があります。
- データ完全性の侵害: 意図しない、または悪意のあるオブジェクトの上書きや削除は、データの完全性を損ないます。ログがないと、いつ、どのようにデータが変更されたかを追跡できず、復旧作業や原因究明が難しくなります。
- コンプライアンス違反: 多くの規制やコンプライアンス基準(例: GDPR、HIPAA、PCI DSS、ISO 27001)では、機密データに対する変更操作のログ保持が義務付けられています。オブジェクトレベルの書き込みログがない場合、これらの要件を満たせず、監査での指摘や法的リスク、罰金につながる可能性があります。
- フォレンジック調査の困難さ: セキュリティインシデント発生時、詳細なオブジェクトアクセスログがないと、攻撃の経緯や影響範囲を正確に特定するためのフォレンジック調査が著しく困難になります。
- ユーザー行動の分析不足: 特定のS3オブジェクトに対するユーザーやアプリケーションの行動パターンを分析し、異常検知や内部統制の強化に役立てることができません。
対策
S3バケットのオブジェクトレベルの書き込みイベントのログ記録を有効にすることは、データへの変更操作を詳細に可視化し、セキュリティ、コンプライアンス、および運用の要件を満たすための重要な対策です。
- CloudTrail データイベントの有効化: S3オブジェクトレベルのログ記録は、AWS CloudTrail の データイベント として記録されます。CloudTrailトレイルで、対象S3バケットの「書き込み」データイベント(
PutObject
、DeleteObject
など)をログに記録するように設定します。 - CloudWatch Logsへの連携: CloudTrailのログを CloudWatch Logs に送信するように設定します。これにより、ログデータを一元的に管理し、メトリクスフィルターやアラームを設定できるようになります。
- 適切なストレージと保持期間: ログの量が多くなる可能性があるため、S3バケットへのログ保存先を適切に計画し、必要な保持期間を設定します。長期的な保持が必要な場合は、S3のライフサイクルルールを活用してGlacierなどの低コストストレージに移行することも検討します。
- セキュリティ分析ツールとの統合: ログデータをAmazon Athena、Amazon QuickSight、またはサードパーティのSIEM (Security Information and Event Management) ツールと統合することで、高度なセキュリティ分析や視覚化が可能になります。
- アラームと通知の設定: 不審な書き込みパターンや、特定の重要オブジェクトの削除などを検知するためのCloudWatchアラームを設定し、Amazon SNSなどを通じて関係者に通知を送信します。
修復方法
AWSコンソールでの修復手順
AWSコンソールを使用して、S3バケットのオブジェクトレベル書き込みイベントのログ記録を有効にします。
- CloudTrailサービスへ移動: AWSコンソールにログインし、CloudTrail サービスを開きます。
- トレイルの選択: 左側のナビゲーションペインで「トレイル」を選択し、設定を変更したい既存のトレイルを選択します。もしトレイルがない場合は、まず新しいトレイルを作成します。
- データイベントの設定変更: トレイルの詳細ページで、「データイベント」セクションを見つけ、「編集」をクリックします。
- S3セクションの設定: 「S3」セクションまでスクロールします。
- ログイベント: 「データイベントのログ記録」がチェックされていることを確認します。
- データイベントセレクター:
- 「書き込みイベントのみをログ記録」を選択
- 変更の保存: 設定を確認し、「変更を保存」をクリックします。

Terraformでの修復手順
TerraformでS3バケットのオブジェクトレベル書き込みイベントのログ記録を有効にするには、aws_cloudtrail
リソースの event_selector
ブロックを設定します。
前提: 既にCloudTrailトレイルが作成されており、ログがS3バケットに保存され、CloudWatch Logsに送信されていると仮定します。
# 既存のCloudTrailトレイルを参照 (もし既存のものを更新する場合)
# data "aws_cloudtrail" "existing_trail" {
# name = "my-cloudtrail-trail" # あなたのCloudTrailトレイル名に置き換えてください
# }
# 新しいCloudTrailトレイルを作成する場合 (例)
resource "aws_s3_bucket" "cloudtrail_log_bucket" {
bucket = "my-cloudtrail-logs-bucket-unique-12345" # グローバルで一意の名前に変更
force_destroy = true # テスト用。本番環境ではfalseを推奨
tags = {
Name = "CloudTrailLogBucket"
}
}
resource "aws_cloudtrail" "my_cloudtrail_with_s3_data_events" {
name = "my-cloudtrail-with-s3-data-events"
s3_bucket_name = aws_s3_bucket.cloudtrail_log_bucket.id
is_organization_trail = false # 組織トレイルにする場合はtrue
include_global_service_events = true
is_multi_region_trail = true
# CloudWatch Logsへのログ送信設定 (アラームのために推奨)
cloud_watch_logs_group_arn = aws_cloudwatch_log_group.cloudtrail_log_group.arn
cloud_watch_logs_role_arn = aws_iam_role.cloudtrail_cw_role.arn
# S3オブジェクトレベルのデータイベントを設定
event_selector {
read_write_type = "All" # 書き込みイベントのみを対象にする場合は "WriteOnly"
include_management_events = true
# 管理イベントをログに記録するかどうか。通常はtrue。
# S3バケットのデータイベントを指定
data_resource {
type = "AWS::S3::Object"
# すべてのS3バケットのオブジェクトイベントをログに記録する場合:
values = ["arn:aws:s3:::"]
# 特定のS3バケットのオブジェクトイベントをログに記録する場合:
# values = ["${aws_s3_bucket.my_data_bucket.arn}/*"] # 特定のS3バケットを参照
}
}
tags = {
Name = "CloudTrail_S3_DataEvents"
}
}
# CloudTrailログ用のS3バケットポリシー (CloudTrailがログを書き込めるようにする)
resource "aws_s3_bucket_policy" "cloudtrail_log_bucket_policy" {
bucket = aws_s3_bucket.cloudtrail_log_bucket.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Sid = "AWSCloudTrailAclCheck"
Effect = "Allow"
Principal = { Service = "cloudtrail.amazonaws.com" }
Action = "s3:GetBucketAcl"
Resource = aws_s3_bucket.cloudtrail_log_bucket.arn
},
{
Sid = "AWSCloudTrailWrite"
Effect = "Allow"
Principal = { Service = "cloudtrail.amazonaws.com" }
Action = "s3:PutObject"
Resource = "${aws_s3_bucket.cloudtrail_log_bucket.arn}/AWSLogs/${data.aws_caller_identity.current.account_id}/*"
Condition = {
StringEquals = {
"s3:x-amz-acl" = "bucket-owner-full-control"
}
}
}
]
})
}
# CloudWatch Logsグループ (CloudTrailログ用)
resource "aws_cloudwatch_log_group" "cloudtrail_log_group" {
name = "/aws/cloudtrail/my-cloudtrail-with-s3-data-events" # トレイル名と一致させる
retention_in_days = 90 # ログ保持期間を適切に設定
}
# CloudTrailがCloudWatch Logsに書き込むためのIAMロール
resource "aws_iam_role" "cloudtrail_cw_role" {
name = "cloudtrail-to-cloudwatch-logs-role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = {
Service = "cloudtrail.amazonaws.com"
}
},
]
})
}
resource "aws_iam_role_policy" "cloudtrail_cw_policy" {
name = "cloudtrail-cw-logs-policy"
role = aws_iam_role.cloudtrail_cw_role.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Action = [
"logs:CreateLogStream",
"logs:PutLogEvents"
]
Resource = "${aws_cloudwatch_log_group.cloudtrail_log_group.arn}:*"
}
]
})
}
# 現在のAWSアカウント情報とリージョン情報を取得
data "aws_caller_identity" "current" {}
data "aws_region" "current" {}
# 特定のS3データバケットを監視する場合の例 (event_selectorのvaluesと連携)
# resource "aws_s3_bucket" "my_data_bucket" {
# bucket = "my-specific-data-bucket-to-monitor-12345"
# tags = {
# Name = "MyDataBucket"
# }
# }
上記のTerraformコードでは、aws_cloudtrail
リソース内で event_selector
ブロックを設定し、data_resource
タイプを "AWS::S3::Object"
と指定することで、S3オブジェクトレベルのデータイベントのログ記録を有効にしています。
read_write_type = "WriteOnly"
を設定することで、書き込みイベントのみを対象とすることができます。全てのイベントを対象にする場合は"All"
を使用します。values = ["arn:aws:s3:::"]
とすることで、アカウント内のすべてのS3バケットのオブジェクトイベントをログに記録します。- 特定のS3バケットのみを対象にする場合は、
values = ["${aws_s3_bucket.my_data_bucket.arn}/*"]
のように、対象バケットのARNを指定します。(コメントアウトされている部分を参照)
my-cloudtrail-logs-bucket-unique-12345
や your-security-email@example.com
などのプレースホルダーは、実際の環境に合わせて修正してください。
最後に
この記事では、S3バケットのオブジェクトレベル書き込みイベントのログ記録が有効になっていない状態のリスクと、その対策について解説しました。CloudTrailのデータイベントを活用してS3オブジェクトへの変更を詳細にログ記録することは、データセキュリティ、コンプライアンス、およびインシデント対応能力を大幅に向上させるために不可欠です。
貴社のS3バケットでは、オブジェクトレベルの書き込みイベントが適切にログ記録されていますか?ぜひ、この機会に設定を確認・強化してみてください。
この問題の検出は弊社が提供するSecurifyのCSPM機能で簡単に検出及び管理する事が可能です。
運用が非常に楽に出来る製品になっていますので、ぜひ興味がある方はお問い合わせお待ちしております。
最後までお読みいただきありがとうございました。この記事が皆さんの役に立てば幸いです。