CloudTrail証跡のデータイベントで特定のS3バケットやフォルダのみを記録する
はじめに
皆様こんにちは、あかいけです。
CloudTrailでS3のデータイベント(オブジェクトレベルのAPI操作)を記録したいけど、全バケットを対象にするとログ量が膨大になってコストが心配…と思ったことはありませんか?
私はあります。
実は、CloudTrail証跡の 高度なイベントセレクター(Advanced Event Selectors) を使うと、特定のS3バケットや特定のフォルダ(プレフィックス)のみを記録対象にできます。
今回は、CloudTrail証跡で特定のS3バケットやフォルダのみを記録する方法についてまとめます。
本記事ではAWS CLIやTerraformでの設定方法を記載しています。
マネジメントコンソールから手動での設定方法については、以下をご参照ください、
(CloudTrail Lakeが対象ですが、設定方法はCloudTrail証跡と同じです)
データイベントについて
CloudTrailで記録できるイベントには、管理イベントとデータイベントがあります。
管理イベントはAWSリソースに対する管理操作(コントロールプレーン操作)を記録します。
たとえば、S3バケットの作成(CreateBucket)やIAMロールの作成(CreateRole)などが該当します。
一方、データイベントはリソース上またはリソース内で実行される操作(データプレーン操作)を記録します。
そのためデータイベントはログ量が多くなりやすく、また一例として以下のようなサービスや操作が対象となります。
- Amazon S3
- オブジェクトレベルのAPI操作(
GetObject、PutObject、DeleteObjectなど)
- オブジェクトレベルのAPI操作(
- AWS Lambda
- 関数の実行(
Invoke)
- 関数の実行(
- Amazon DynamoDB
- テーブルに対する操作(
PutItem、DeleteItem、UpdateItemなど)
- テーブルに対する操作(
- Amazon SNS
- トピックへの
Publish操作
- トピックへの
- Amazon SQS
- キューへのメッセージ操作
ただし、データイベントの記録には課金が発生します。
なので大規模な環境で全S3バケットを対象にすると、ログ量もコストも膨大になりがちです。
Amazon S3 に配信されたデータイベント
配信されたデータイベント 100,000 件あたり 0.10 USD
そこで活用できるのが 高度なイベントセレクター です。
この機能でARNなどを指定してフィルタリングすることで、以下のような細かい制御が可能になります。
- 特定のS3バケットのみ記録
- 特定のフォルダ(プレフィックス)のみ記録
- 特定のS3バケットやフォルダを除外
CloudTrail証跡での設定方法
特定のS3バケットのみを記録する
特定のバケット内の全オブジェクトを対象にする場合は、以下のように設定します。
| フィールド | オペレーター | 値 |
|---|---|---|
| resources.type | Equals | AWS::S3::Object |
| resources.ARN | StartsWith | arn:aws:s3:::my-bucket/ |
ここで重要なのは、「ARNの末尾に/(スラッシュ)を付けること」です。
スラッシュなしでarn:aws:s3:::my-bucketと指定すると、my-bucket-logsやmy-bucket-backupなど、名前がmy-bucketで始まる他のバケットも対象になってしまいます。
特定のフォルダ(プレフィックス)のみを記録する
バケット内の特定のフォルダだけを対象にする場合は、以下のように設定します。
| フィールド | オペレーター | 値 |
|---|---|---|
| resources.type | Equals | AWS::S3::Object |
| resources.ARN | StartsWith | arn:aws:s3:::my-bucket/important-data/ |
これでmy-bucketバケット内のimportant-data/配下のオブジェクトのみが記録されます。
特定のバケットを除外する
逆に、特定のバケットを除外して他の全バケットを記録したい場合は、NotStartsWithを使います。
| フィールド | オペレーター | 値 |
|---|---|---|
| resources.type | Equals | AWS::S3::Object |
| resources.ARN | NotStartsWith | arn:aws:s3:::logs-bucket/ |
AWS CLIでの設定
AWS CLIで証跡を作成し、データイベントを設定する流れを説明します。
1. 証跡の作成
まずcreate-trailコマンドでCloudtrail証跡を作成します。
aws cloudtrail create-trail \
--name my-trail \
--s3-bucket-name my-cloudtrail-logs-bucket
なお、S3バケットには事前にCloudTrailからの書き込みを許可するバケットポリシーを設定しておく必要があります。
2. データイベントの設定
次にput-event-selectorsコマンドで高度なイベントセレクターを設定します。
aws cloudtrail put-event-selectors \
--trail-name my-trail \
--advanced-event-selectors '[
{
"Name": "Log S3 data events for specific bucket",
"FieldSelectors": [
{ "Field": "eventCategory", "Equals": ["Data"] },
{ "Field": "resources.type", "Equals": ["AWS::S3::Object"] },
{ "Field": "resources.ARN", "StartsWith": ["arn:aws:s3:::my-bucket/"] }
]
}
]'
3. 記録の開始
最後にstart-loggingコマンドで記録を開始します。
aws cloudtrail start-logging --name my-trail
証跡の状態はget-trail-statusコマンドで確認できます。
aws cloudtrail get-trail-status --name my-trail
複数条件を組み合わせる
高度なイベントセレクターでは複数の条件を組み合わせることもできます。
たとえば、特定のバケットのPutObjectとDeleteObjectイベントのみを記録する場合は以下の通りです。
aws cloudtrail put-event-selectors \
--trail-name my-trail \
--advanced-event-selectors '[
{
"Name": "Log PutObject and DeleteObject for specific bucket",
"FieldSelectors": [
{ "Field": "eventCategory", "Equals": ["Data"] },
{ "Field": "resources.type", "Equals": ["AWS::S3::Object"] },
{ "Field": "resources.ARN", "StartsWith": ["arn:aws:s3:::my-bucket/"] },
{ "Field": "eventName", "Equals": ["PutObject", "DeleteObject"] }
]
}
]'
Terraformでの設定
Terraformで設定する場合は、
aws_cloudtrailリソースのadvanced_event_selectorブロックを使用します。
ご参考までに、いくつか設定例を載せておきます。
特定のS3バケットのみを記録する
resource "aws_cloudtrail" "example" {
name = "my-trail"
s3_bucket_name = "my-cloudtrail-logs-bucket"
# 高度なイベントセレクターの設定
advanced_event_selector {
name = "Log S3 data events for specific bucket"
field_selector {
field = "eventCategory"
equals = ["Data"]
}
field_selector {
field = "resources.type"
equals = ["AWS::S3::Object"]
}
field_selector {
field = "resources.ARN"
starts_with = ["${aws_s3_bucket.target.arn}/"]
}
}
}
特定のフォルダ(プレフィックス)のみを記録する
resource "aws_cloudtrail" "example" {
name = "my-trail"
s3_bucket_name = "my-cloudtrail-logs-bucket"
advanced_event_selector {
name = "Log S3 data events for specific prefix"
field_selector {
field = "eventCategory"
equals = ["Data"]
}
field_selector {
field = "resources.type"
equals = ["AWS::S3::Object"]
}
field_selector {
field = "resources.ARN"
starts_with = ["${aws_s3_bucket.target.arn}/important-data/"]
}
}
}
特定のバケットを除外する
resource "aws_cloudtrail" "example" {
name = "my-trail"
s3_bucket_name = "my-cloudtrail-logs-bucket"
advanced_event_selector {
name = "Log all S3 data events except specific buckets"
field_selector {
field = "eventCategory"
equals = ["Data"]
}
field_selector {
field = "resources.type"
equals = ["AWS::S3::Object"]
}
field_selector {
field = "resources.ARN"
# 除外したいバケットを指定する
not_starts_with = [
"${aws_s3_bucket.logs.arn}/",
"${aws_s3_bucket.backup.arn}/"
]
}
}
}
複数条件を組み合わせる
resource "aws_cloudtrail" "example" {
name = "my-trail"
s3_bucket_name = "my-cloudtrail-logs-bucket"
advanced_event_selector {
name = "Log PutObject and DeleteObject for specific buckets"
field_selector {
field = "eventCategory"
equals = ["Data"]
}
field_selector {
field = "resources.type"
equals = ["AWS::S3::Object"]
}
field_selector {
field = "resources.ARN"
starts_with = ["${aws_s3_bucket.target.arn}/"]
}
field_selector {
field = "eventName"
equals = ["PutObject", "DeleteObject"]
}
field_selector {
field = "readOnly"
equals = ["false"]
}
}
}
なお、advanced_event_selectorとevent_selector(基本イベントセレクター)は併用できません。
そのため複数のイベントセレクターを設定したい場合は、複数のadvanced_event_selectorで設定します。
さいごに
以上、CloudTrail証跡のデータイベントで特定のS3バケットやフォルダのみを記録する方法でした。
高度なイベントセレクターを使うことで、必要なログだけを効率的に記録できるようになります。
全バケットを対象にするよりもコストを抑えられますし、ログのノイズも減るので分析もしやすくなりますね。
この記事が誰かのお役に立てば幸いです。








