querying-aws-s3 について
AthenaでAmazon S3のメタデータとStorage Lensのシステムテーブルをクエリするスキルです。AWSユーザー向けに、設定、テーブル選択、SQLクエリ、アクセス管理を案内します。
主な機能
- 01オブジェクト一覧・ジャーナル・注釈テーブルのクエリ
- 02Storage Lensメトリクスの分析
- 03S3 Metadataとテーブル出力の設定
- 04Athena SQLと権限設定の案内
活用シーン
- 01オブジェクト数の集計とタグ検索
- 02アップロード、削除、リクエスト元の監査
- 03注釈テキストやJSON値の検索
- 04バケットの容量とアクティビティ指標の確認
MCP 対応
サンドボックス実行と監査ログにはAWS MCPサーバーを推奨します。各コマンドはAWS CLIでも実行できます。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ aws/ agent-toolkit-for-aws --skill querying-aws-s3インストール後、Claude Code で/querying-aws-s3を入力して読み込まれたか確認します。
詳細
AWS S3 システムテーブルをクエリする
概要
サンドボックス化された実行と監査ログには、AWS MCP サーバーとの併用が最適です。以下のコマンドはすべて AWS CLI を使用しており、AWS 認証情報が設定された環境であればどこでも実行できます。IAM ロールまたは一時的な認証情報を使用し、長期間有効なアクセスキーは使用しないでください。
Amazon S3 Metadata は、汎用バケットのオブジェクトレベルのメタデータを収集する、継続的に更新される Apache Iceberg テーブルを提供します。S3 Storage Lens は、集計されたストレージとアクティビティのメトリクスを Iceberg テーブルとしてエクスポートします。どちらも読み取り専用で、AWS 管理の aws-s3 テーブルバケットに保存され、Amazon Athena からクエリできます。
システムテーブルは、生の S3 API(list-objects-v2、head-object)よりも推奨されます。理由は次のとおりです。
list-objects-v2はページあたり最大 1000 個のオブジェクトをページネーションするため、大規模なバケット(数百万から数十億個のオブジェクト)では非効率です。インベントリテーブルなら、どのような規模でもSELECT COUNT(*)の結果を数秒で取得できます。list-objects-v2では、オブジェクトをアップロードしたユーザー、使用された IP アドレス、またはオブジェクトが削除された日時を特定できません。requester、source_ip_address、削除イベントの追跡情報があるのはジャーナルテーブルだけです。- タグによるフィルタリングには、オブジェクトごとに
get-object-taggingが必要です。インベントリテーブルには、クエリ可能なマップ列としてobject_tagsがあります。
判断ツリー
| ユーザーの目的 | このスキルを使用しますか? | テーブル | 代替手段 |
|---|---|---|---|
| バケット内のオブジェクト数を知りたい | はい | インベントリ | — |
| 最近アップロードまたは削除されたものを知りたい | はい | ジャーナル | — |
| オブジェクトを書き込んだ、または削除したユーザーを監査したい | はい | ジャーナル(requester、source_ip) | — |
| ストレージクラスの内訳を知りたい | はい | インベントリ | — |
| タグまたはユーザーメタデータでオブジェクトを検索したい | はい | インベントリ | — |
| アノテーションの内容を検索したい | はい | アノテーション | 単一のオブジェクト → 直接 API get-object-annotation |
| アノテーションを書き込む、または更新したい | いいえ | — | 直接 API:put-object-annotation(テーブルは読み取り専用です) |
| オブジェクト内のデータをクエリしたい | いいえ | — | querying-data-lake |
| バケットレベルのストレージメトリクスや傾向を知りたい | はい | Storage Lens テーブル | — |
| メタデータの追跡を有効にしたい | はい | 有効化のセクションを参照 | — |
よくあるタスク
1. 設定済みかどうかを確認する
クエリを実行する前に、対象バケットで S3 Metadata が有効になっていることを確認してください。
aws s3api get-bucket-metadata-configuration --bucket <BUCKET> --region <REGION>
応答の解釈:
MetadataConfigurationNotFoundエラー → 有効になっていません。以下の「有効化」セクションを参照してください。TableStatus: ACTIVE→ クエリを実行できます。TableStatus: BACKFILLING→ クエリは実行できますが、インベントリが不完全な場合があります。TableStatus: FAILED→ エラーフィールドを確認してください(通常は IAM が原因です)。
Storage Lens の場合:
aws s3control get-storage-lens-configuration --account-id <ACCOUNT> --config-id <CONFIG_ID> --region <REGION>
DataExport.StorageLensTableDestination.IsEnabled: true を確認してください。
2. 有効化する(未設定の場合)
バケットで S3 Metadata を有効にする:
aws s3api create-bucket-metadata-configuration \
--bucket <BUCKET> \
--region <REGION> \
--metadata-configuration '{
"JournalTableConfiguration": {"RecordExpiration": {"Expiration": "DISABLED"}},
"InventoryTableConfiguration": {"ConfigurationState": "ENABLED"}
}'
アノテーションも有効にする場合(サービスロールが必要です):
aws s3api create-bucket-metadata-configuration \
--bucket <BUCKET> \
--region <REGION> \
--metadata-configuration '{
"JournalTableConfiguration": {"RecordExpiration": {"Expiration": "ENABLED", "Days": 90}},
"InventoryTableConfiguration": {"ConfigurationState": "ENABLED"},
"AnnotationTableConfiguration": {"ConfigurationState": "ENABLED", "Role": "<ROLE_ARN>"}
}'
Storage Lens S3 Tables エクスポートを有効にする:
aws s3control put-storage-lens-configuration \
--account-id <ACCOUNT> \
--config-id <CONFIG_ID> \
--region <REGION> \
--storage-lens-configuration '{
"Id": "<CONFIG_ID>",
"IsEnabled": true,
"AccountLevel": {"BucketLevel": {}},
"DataExport": {
"StorageLensTableDestination": {"IsEnabled": true}
}
}'
Glue に S3 Tables フェデレーテッドカタログを登録する(Athena からのアクセスに必要です):
aws glue create-catalog --region <REGION> --cli-input-json '{
"Name": "s3tablescatalog",
"CatalogInput": {
"FederatedCatalog": {
"Identifier": "arn:aws:s3tables:<REGION>:<ACCOUNT>:bucket/*",
"ConnectionName": "aws:s3tables"
}
}
}'
セットアップに必要な権限と IAM ロールの要件については、以下のセキュリティに関する考慮事項を参照してください。
3. 権限を確認する
クエリの実行には、次のものが必要です。
- Athena の実行権限
- S3 Tables の読み取り権限(「セキュリティに関する考慮事項」に記載の最小権限ポリシーを参照)
- Glue に登録された S3 Tables フェデレーテッドカタログ(
s3tablescatalog) - 出力先で SSE-KMS 暗号化が設定された Athena ワークグループ
CATALOG_NOT_FOUND エラーが発生する場合、Glue との統合が有効になっていない可能性があります。次を参照してください:
S3 Tables と AWS 分析サービスの統合
4. 対象テーブルを特定する
S3 Metadata テーブル — 名前空間は b_<bucket-name> です。
| テーブル | 取得できる情報 |
|---|---|
journal | イベントログ — CREATE、DELETE、UPDATE_METADATA、およびアノテーションイベントをすべて記録します。ほぼリアルタイムです。 |
inventory | 現在の状態 — オブジェクトごとに1行(最新バージョン)を記録します。1時間以内に更新されます。 |
annotation | アノテーションのペイロード — text_value 列に全コンテンツが格納されます。ほぼリアルタイムです。 |
Storage Lens テーブル — 名前空間は lens_<config-id>_exp です。
| テーブル | 取得できる情報 |
|---|---|
default_storage_metrics | バケット/プレフィックスごとのオブジェクト数、サイズ、ストレージクラスの内訳。毎日更新されます。 |
default_activity_metrics | バケット/プレフィックスごとの GET/PUT/DELETE リクエスト数。毎日更新されます。 |
bucket_property_metrics | バケットの設定:バージョニング、暗号化、ライフサイクル設定。毎日更新されます。 |
5. クエリを実行する
クエリ構文:
"s3tablescatalog/aws-s3"."<namespace>"."<table>"
制約:
-
実行前に、ワークグループと出力先を必ず確認してください
-
Athena ワークグループで、クエリ結果に SSE-KMS 暗号化が適用されることを必ず確認してください
-
テーブルは読み取り専用で、INSERT/UPDATE/DELETE は実行できないことをユーザーに必ず伝えてください
-
このスキルに記載されているキー列を使用してクエリを作成してください。完全なスキーマが必要な場合(例:AWS によって新しい列が追加された場合)は、いずれか1つの名前空間で
get-tablesを1回実行してください。同じテーブルタイプのすべてのインスタンスでスキーマは同一です。aws glue get-tables --catalog-id "<ACCOUNT>:s3tablescatalog/aws-s3" --database-name "<namespace>" --region <REGION>
Journal — 変更者と変更内容を監査する:
SELECT key, record_type, record_timestamp, requester, source_ip_address
FROM "s3tablescatalog/aws-s3"."b_<bucket>"."journal"
WHERE record_type = 'DELETE'
AND record_timestamp > current_timestamp - interval '24' hour
ORDER BY record_timestamp DESC;
Journal — アノテーションイベントを追跡する:
SELECT key, record_type, annotation.name, record_timestamp
FROM "s3tablescatalog/aws-s3"."b_<bucket>"."journal"
WHERE record_type IN ('CREATE_ANNOTATION', 'DELETE_ANNOTATION', 'UPDATE_ANNOTATION_METADATA')
ORDER BY record_timestamp DESC LIMIT 20;
Inventory — ストレージクラスでオブジェクトを検索する:
SELECT key, size, storage_class, last_modified_date
FROM "s3tablescatalog/aws-s3"."b_<bucket>"."inventory"
WHERE storage_class = 'GLACIER'
ORDER BY size DESC LIMIT 50;
Inventory — タグでオブジェクトを検索する:
SELECT key, size, object_tags
FROM "s3tablescatalog/aws-s3"."b_<bucket>"."inventory"
WHERE object_tags['environment'] = 'staging';
Annotation — ペイロード全体を検索する:
SELECT object_key, name, text_value
FROM "s3tablescatalog/aws-s3"."b_<bucket>"."annotation"
WHERE text_value LIKE '%error%';
Annotation — JSON フィールドを抽出する:
SELECT object_key, json_extract_scalar(text_value, '$.status') as status
FROM "s3tablescatalog/aws-s3"."b_<bucket>"."annotation"
WHERE name = 'pipeline_status'
AND json_extract_scalar(text_value, '$.status') = 'FAILED';
Storage Lens — ストレージの分布:
SELECT *
FROM "s3tablescatalog/aws-s3"."lens_<config-id>_exp"."default_storage_metrics"
LIMIT 20;
使い分け:Athena と直接 API
| シナリオ | 使用する方法 |
|---|---|
| 既知の単一オブジェクトとアノテーション名 | 直接 API:get-object-annotation |
| 多数のオブジェクトを対象に集計/カウントする | annotation テーブルまたは inventory テーブルに対する Athena |
| アノテーションのペイロード全体を全文検索する | LIKE または json_extract_scalar を使った Athena |
| アノテーションを書き込む/更新する | 直接 API:put-object-annotation(テーブルは読み取り専用です) |
| バケットで機能が設定されていない | 直接 API のループ(list-objects-v2 + head-object)。S3 Metadata の有効化を提案してください |
トラブルシューティング
| エラー | 原因 | 対処方法 |
|---|---|---|
CATALOG_NOT_FOUND | S3 Tables が Glue に登録されていない | 統合を有効にします:S3 コンソール > Table buckets > Enable integration |
| journal の結果が空 | 機能を有効にした直後で、イベントがまだ記録されていない | オブジェクトをアップロード/削除して、約1分待ちます |
| inventory の結果が空 | テーブルがまだ BACKFILLING 状態 | ステータスを確認し、ACTIVE になるまで待ちます(オブジェクト数に応じて数分から数時間) |
テーブルへのクエリで AccessDenied | s3tables:GetTable または GetTableMetadataLocation が不足している | 下記の「セキュリティに関する考慮事項」を参照してください |
| 名前空間が違う | バケット名にピリオドが含まれている | 名前空間ではピリオドがアンダースコアに変換されます:my.bucket → b_my_bucket |
| Storage Lens のデータがない | 初回のデータ配信には最大48時間かかる | 待ちます。過去データのバックフィルはありません |
セキュリティに関する考慮事項
最小権限の IAM ポリシー
ワイルドカードを使用せず、特定のテーブルバケット ARN に権限を限定してください。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3tables:GetTable",
"s3tables:GetTableMetadataLocation",
"s3tables:GetTableData",
"s3tables:GetNamespace",
"s3tables:ListTables",
"s3tables:ListNamespaces",
"s3tables:GetTableBucket"
],
"Resource": [
"arn:aws:s3tables:<REGION>:<ACCOUNT>:bucket/aws-s3",
"arn:aws:s3tables:<REGION>:<ACCOUNT>:bucket/aws-s3/*"
]
}
]
}
データの機密性
Journal のクエリ結果には、機密フィールドが含まれる場合があります。
requester— リクエストを実行した AWS アカウント ID またはサービスプリンシパルsource_ip_address— リクエスト元の IP アドレス
これらのフィールドを含むクエリ結果は、暗号化され、アクセスが制御された場所に保存してください。IP アドレスやプリンシパル識別子を含むクエリ出力をそのまま記録したり共有したりしないでください。
クエリ結果の暗号化
クエリ結果を保存時に暗号化するには、EncryptionConfiguration を使用して Athena ワークグループを設定してください。
{
"ResultConfiguration": {
"EncryptionConfiguration": {
"EncryptionOption": "SSE_KMS",
"KmsKey": "arn:aws:kms:<REGION>:<ACCOUNT>:key/<KEY_ID>"
}
}
}
監査証跡
Athena(StartQueryExecution、GetQueryResults)および S3 Tables(s3tables:GetTableData)の API 呼び出しについて CloudTrail ロギングを有効にし、誰がどのメタデータをクエリしたかの監査証跡を維持します。CloudTrail ログが SSE-KMS で暗号化され、アクセスログが有効になっているバケットに保存されるようにしてください。