0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

CloudTrailのS3データイベントをAthenaでクエリーする

0
Last updated at Posted at 2026-06-11

1. この記事を書いた背景

筆者が関わる仕事で、S3バケットへのファイルアップロードなどの S3のオブジェクトレベルのイベントを記録 して、作業エビデンスの取得トラブルシュート で活用することになりました。

S3のオブジェクトレベルのイベントの記録には、 CloudTrailの証跡 の中の 「S3データイベント」 というS3のオブジェクトレベルのイベントを取得できる機能を利用しました。

ただし、S3データイベントはCloudTrailの画面の「イベント履歴」からは検索ができないという制約があり、 証跡保管先のS3バケットをAthenaでクエリー検索 することにしました。

image.png

image.png

Athenaで目当てのS3のイベントを検索しようとすると参考になる公開情報があまり見つからず、目当てのイベントをフィルターできるクエリーの準備に手間取ったので、この記事では筆者が用意したクエリー例をご紹介します。

なお、CloudTrailのイベントをAthenaでクエリー検索するための テーブル作成の手順 は以下の記事などを参照ください。

2. S3イベントを取得・検索する他の方法

AWS上でS3イベントを取得・検索する手段は今回採用した以外にも提供されているのでご紹介しておきます。

S3イベントの取得方法

S3のオブジェクトレベルのイベントを取得する他の方法としては、S3バケット単位で「S3サーバーログ」を取得する方法もあります。

image.png

ただし、今回はオブジェクトレベルのイベントを記録しておきたいバケットが多数あったため、 複数バケットのイベント記録をまとめて有効化できるCloudTrailのS3データイベントを採用 しました。

参考までに、以下の記事にて双方の機能の特徴が詳しく紹介されています。

取得したS3イベントの検索方法

CloudTrailの証跡はS3だけでなく、CloudWatchにも二重で保管することができるため、S3上のログをAthenaで検索するだけでなく、 CloudWatch上のログをCloudWatch Logs Insightsで検索 することも可能です。
今回はログ保管のコストが二重でかかってしまうので採用しませんでした。

また、 CloudTrail Lake というCloudTrailの機能でも、Athenaと同じような証跡のクエリー検索が可能です。
今回はCloudTrail Lakeセットアップ前のログは検索できないという制約が不便で採用していません。

なお、CloudTrail Lakeはちょうど2026年5月31日をもって新規利用ができなくなったので、これからS3データイベントの検索を新規で検討される方にとっては、AthenaとCloudWatch Logs Insightsのどちらかが選択肢になると思います。

一方、CloudTrailのS3データイベントではなく、S3サーバーログを検索したい場合、方法はAthena一択 になると思います。

3. 各種S3データイベントを検索できるAthenaのクエリー例

ここからはいろんな条件にマッチするS3データイベントを検索するのに筆者が用意したAthenaのクエリーのサンプルをご紹介します。

3-1. 特定のS3バケットの特定のパスのイベントのクエリー

2026年6月1日9時(UTC)より後の特定のS3バケットの特定のパスのイベントを条件にイベント日時、S3バケット名、S3パス、操作の種類、操作を行ったIAMプリンシパルを昇順で100件クエリーする例
SELECT 
  eventtime, 
  json_extract_scalar(requestparameters, '$.bucketName') as bucket_name,
  json_extract_scalar(requestparameters, '$.key') as object_key,
  eventname, 
  useridentity.type AS identity_type,
  useridentity.arn  AS identity_arn
FROM <Athenaのテーブル名に置き換え>
WHERE json_extract_scalar(requestparameters, '$.bucketName') = '<バケット名に置き換え>'
  AND json_extract_scalar(requestparameters, '$.key') = '<S3キー(バケット内のパス+ファイル名)に置き換え。例「path/object-name」>'
  AND eventtime > '2026-06-01T09:00:00'
ORDER BY eventtime ASC
LIMIT 100;

クエリーのポイント

  • S3イベントが発生した バケットやパスの情報 はAthenaテーブルの requestparameters に含まれます。requestparametersは string型(JSON文字列) でバケットやパス以外の項目も含むため、json_extract_scalar関数 を使ってバケットやパスの項目だけを扱えるようにしています
  • イベント発生日時 はAthenaテーブルの eventtime常にUTCで保管 されるため、その前提でクエリー検索する必要があります
  • PutObject、GetObjectなどの 操作の種類 はAthenaテーブルの eventname に保管されます
  • 操作を行ったIAMプリンシパル はAthenaテーブルの useridentitystruct型 で保管されます。useridentityはいろんな項目を含みますが、IAMUser、AssumedRoleなどの type と操作を行ったIAMプリンシパルの arn が分かると便利なので、その2つを ドット記法でネスト して抽出しています

3-2. 特定のS3バケットのファイルアップロードのイベントのクエリー

2026年6月1日0時(UTC)より後の特定のS3バケットのファイルアップロード完了を条件にイベント日時、S3バケット名、S3パス、操作の種類、操作を行ったIAMプリンシパルを昇順で100件クエリーする例
SELECT 
  eventtime, 
  json_extract_scalar(requestparameters, '$.bucketName') as bucket_name,
  json_extract_scalar(requestparameters, '$.key') as object_key,
  eventname, 
  useridentity.type AS identity_type,
  useridentity.arn  AS identity_arn
FROM <Athenaのテーブル名に置き換え>
WHERE json_extract_scalar(requestparameters, '$.bucketName') = '<バケット名に置き換え>'
  AND eventname IN ('PutObject', 'CopyObject', 'CompleteMultipartUpload', 'PostObject')
  AND eventtime > '2026-06-01'
ORDER BY eventtime ASC
LIMIT 100;

クエリーのポイント

  • 操作の種類 はAthenaテーブルの eventname に保管されます。ファイルアップロードと一口に言っても、イベント名は特定のS3バケットから 別のS3バケットへのコピー の場合は CopyObjectマルチパートアップロード 完了時は CompleteMultipartUploadHTMLフォーム(ブラウザPOST) でのアップロードの場合は PostObject 、その他の一般的なアップロードの場合は PutObject などいろんなパターンがありうるので、いずれかにマッチする場合を取得できるよう IN で条件指定しています

3-3. 特定のS3バケットからのファイルダウンロードのイベントのクエリー

2026年6月1日0時(UTC)より後の特定のS3バケットのファイルダウンロードを条件にイベント日時、S3バケット名、S3パス、操作の種類、操作を行ったIAMプリンシパルを昇順で100件クエリーする例
SELECT 
  eventtime, 
  json_extract_scalar(requestparameters, '$.bucketName') as bucket_name,
  json_extract_scalar(requestparameters, '$.key') as object_key,
  eventname, 
  useridentity.type AS identity_type,
  useridentity.arn  AS identity_arn
FROM <Athenaのテーブル名に置き換え>
WHERE json_extract_scalar(requestparameters, '$.bucketName') = '<バケット名に置き換え>'
  AND eventname = 'GetObject'
  AND eventtime > '2026-06-01'
ORDER BY eventtime ASC
LIMIT 100;

クエリーのポイント

  • 操作の種類 はAthenaテーブルの eventname に保管されるので、ファイルダウンロードに対応する GetObject を条件指定しています

3-4. 特定のS3バケットからのファイル削除のイベントのクエリー

2026年6月1日0時(UTC)より後の特定のS3バケットのファイル削除を条件にイベント日時、S3バケット名、S3パス、操作の種類、操作を行ったIAMプリンシパルを昇順で100件クエリーする例
SELECT 
  eventtime, 
  json_extract_scalar(requestparameters, '$.bucketName') as bucket_name,
  json_extract_scalar(requestparameters, '$.key') as object_key,
  eventname, 
  useridentity.type AS identity_type,
  useridentity.arn  AS identity_arn
FROM <Athenaのテーブル名に置き換え>
WHERE json_extract_scalar(requestparameters, '$.bucketName') = '<バケット名に置き換え>'
  AND eventtime > '2026-06-01'
  AND eventName in ('DeleteObject', 'DeleteObjects')
ORDER BY eventTime ASC
LIMIT 100;

クエリーのポイント

  • 操作の種類 はAthenaテーブルの eventname に保管されます。ファイル削除のイベントは DeleteObjectDeleteObjects の可能性があるのでその2つを条件指定しています。
  • S3パスの情報は、DeleteObject の場合は requestparameterskey で取得できます。ただ、DeleteObjects の場合はどの項目で取得できるか 分かりませんでした

3-5. 特定のS3バケットのファイルの一覧取得のイベントのクエリー

2026年6月1日0時(UTC)より後の特定のS3バケットのファイル一覧取得を条件にイベント日時、S3バケット名、S3パス、操作の種類、操作を行ったIAMプリンシパルを昇順で100件クエリーする例
SELECT 
  eventtime, 
  json_extract_scalar(requestparameters, '$.bucketName'),
  json_extract_scalar(requestparameters, '$.prefix'),
  eventname, 
  useridentity.type AS identity_type,
  useridentity.arn  AS identity_arn
FROM <Athenaのテーブル名に置き換え>
WHERE json_extract_scalar(requestparameters, '$.bucketName') = '<バケット名に置き換え>'
  AND json_extract_scalar(requestparameters, '$.prefix') = 'リストを行ったバケット内のパスに置き換え。例「test/」'
  AND eventtime > '2026-06-01'
  AND eventName IN ('ListObjects', 'ListObjectsV2')
ORDER BY eventTime ASC
LIMIT 100;

クエリーのポイント

  • 操作の種類 はAthenaテーブルの eventname に保管されます。ファイル一覧取得のイベントは ListObjectsListObjectsV2 の可能性があるのでその2つを条件指定しています。
  • S3パスの情報は、ここまでの他のイベントの場合と違い、requestparametersprefix で取得できるため、そちらを指定するようにしています

3-6. 特定のS3バケットでエラーに終わったイベントのクエリー

2026年6月1日0時(UTC)より後の特定のS3バケットでエラーになった操作を条件にイベント日時、S3バケット名、S3パス、操作の種類、操作を行ったIAMプリンシパル、エラーの内容を昇順で100件クエリーする例
SELECT
  eventTime, 
  json_extract_scalar(requestparameters, '$.bucketName') as bucket_name,
  json_extract_scalar(requestparameters, '$.key') as object_key,
  eventname, 
  useridentity.type AS identity_type,
  useridentity.arn  AS identity_arn,
  errorcode,
  errormessage
FROM <Athenaのテーブル名に置き換え>
WHERE json_extract_scalar(requestparameters, '$.bucketName') =  '<バケット名に置き換え>'
  AND eventtime > '2026-06-01'
  AND errorcode <> ''
ORDER BY eventTime ASC
LIMIT 100;

クエリーのポイント

  • エラーが起きたイベントの場合、Athenaテーブルの errorcode がブランク以外になるようなので、そのように条件指定するようにしています
  • さらに、Athenaテーブルの errormessage にエラーの詳細が出るので、そちらも取得するようにしています

3-7. 参考までに、ライフサイクルイベントはクエリーできない

筆者はS3バケットにてライフサイクルルールを使ってファイルがアップロードされてから一定期間後に自動削除されるように設定してました。
ファイル自動削除のライフサイクルイベントのクエリーも試したのですが、上手くいかずで、調べたところリンク先のマニュアルで CloudTrailのS3データイベントではライフサイクルイベントを収集していない ことが明記されていました。

Amazon S3 Lifecycle actions aren't captured by AWS CloudTrail object level logging. CloudTrail captures API requests made to external Amazon S3 endpoints, whereas S3 Lifecycle actions are performed by using internal Amazon S3 endpoints.
You can enable Amazon S3 server access logs in an S3 bucket to capture S3 Lifecycle-related actions, such as object transitions to another storage class and object expirations that result in permanent deletion or logical deletion. For more information, see Logging requests with server access logging.

ライフサイクルイベント収集が必須の場合は、S3サーバーログを保管する必要があるとのことです。

4. 最後に

CloudTrailにてS3データイベントを取得するようにしていても、急にAthenaで目当てのS3のデータイベントを検索しようとしてもAthenaテーブルの項目や、どういう時にどのようなログが出るかを理解していないとなかなか検索が上手くいかないなと思ったので、筆者が実際に上手く実行できたクエリーをご紹介しました。
ここまでの内容がお役に立てば幸いです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?