【小ネタ】Amazon Athena で CloudTrail の S3 データイベントを拡張リクエスト ID を含めてクエリする際にハマったこと
猫とアポロチョコが好きな m.hayakawa です。
今回は Amazon Athena で CloudTrail の S3 データイベントをクエリする際に直面した問題に関する小ネタをご紹介します。
Athena で CloudTrail のテーブルを作る
CloudTrail の設定で特定の S3 のデータイベント取得を有効化し、出力対象の S3 バケットに対して下記のように Athena でテーブルを作成します。
CREATE EXTERNAL TABLE cloudtrail_logs (
eventVersion STRING,
userIdentity STRUCT<
type: STRING,
principalId: STRING,
arn: STRING,
accountId: STRING,
invokedBy: STRING,
accessKeyId: STRING,
userName: STRING,
sessionContext: STRUCT<
attributes: STRUCT<
mfaAuthenticated: STRING,
creationDate: STRING
>,
sessionIssuer: STRUCT<
type: STRING,
principalId: STRING,
arn: STRING,
accountId: STRING,
username: STRING
>,
ec2RoleDelivery: STRING,
webIdFederationData: STRUCT<
federatedProvider: STRING,
attributes: MAP<STRING,STRING>
>
>
>,
eventTime STRING,
eventSource STRING,
eventName STRING,
awsRegion STRING,
sourceIpAddress STRING,
userAgent STRING,
errorCode STRING,
errorMessage STRING,
requestParameters STRING,
responseElements STRING,
additionalEventData STRING,
requestId STRING,
eventId STRING,
resources ARRAY<STRUCT<
arn: STRING,
accountId: STRING,
type: STRING
>>,
eventType STRING,
apiVersion STRING,
readOnly STRING,
recipientAccountId STRING,
serviceEventDetails STRING,
sharedEventID STRING,
vpcEndpointId STRING,
tlsDetails STRUCT<
tlsVersion: STRING,
cipherSuite: STRING,
clientProvidedHostHeader: STRING
>
)
COMMENT 'CloudTrail logs table'
PARTITIONED BY (year string, month string)
ROW FORMAT SERDE 'org.apache.hive.hcatalog.data.JsonSerDe'
STORED AS INPUTFORMAT 'com.amazon.emr.cloudtrail.CloudTrailInputFormat'
OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION 's3://<CloudTrailの保存先S3バケット>/AWSLogs/<アカウントID>/CloudTrail/'
TBLPROPERTIES ('classification'='cloudtrail');
また、特定の月の範囲を指定して、テーブルのパーティション列を作成します。
ALTER TABLE cloudtrail_logs
ADD PARTITION
(year='2025',month='05')
location 's3://<CloudTrailの保存先S3バケット>/AWSLogs/<アカウントID>/CloudTrail/ap-northeast-1/2025/05/';
クエリ実行とエラー
S3 の拡張リクエスト ID などを additionalEventData の JSON から抽出するために、以下のようなクエリを実行しました。
SELECT
eventTime,
eventName,
userIdentity,
sourceIpAddress,
requestId,
json_extract_scalar(additionalEventData, '$.x-amz-id-2') as s3_extended_request_id,
requestParameters,
responseElements
FROM
cloudtrail_logs
CROSS JOIN UNNEST(resources) AS t(resource)
WHERE
eventSource = 's3.amazonaws.com'
AND
eventName ='GetObject'
ORDER BY
eventTime DESC
LIMIT 100;
しかし、下記のようなエラーが発生しました。
INVALID_FUNCTION_ARGUMENT: Invalid JSON path: '$.x-amz-id-2'
このクエリは、クエリで修飾されていない限り、「default」データベースに対して実行されました。エラーメッセージを フォーラム に投稿するか、クエリ ID: EXAMPLE01-0123-0123-0123-012345EXAMPLE とともに カスタマーサポート にお問い合わせください。
解決方法
以下のようにクエリを修正することで問題を解決できました:
SELECT
eventTime,
eventName,
userIdentity,
sourceIpAddress,
requestId,
json_extract_scalar(additionalEventData, '$["x-amz-id-2"]') as s3_extended_request_id,
requestParameters,
responseElements
FROM
cloudtrail_logs
CROSS JOIN UNNEST(resources) AS t(resource)
WHERE
eventSource = 's3.amazonaws.com'
AND
eventName ='GetObject'
ORDER BY
eventTime DESC
LIMIT 100;
原因と解決策
JSON のキー名にハイフン(-)が含まれると、ドット表記法が使えないようです。
json_extract_scalar(additionalEventData, '$.x-amz-id-2') as s3_extended_request_id,
そのため、ブラケット表記法に修正することで、エラーが解消できました。
json_extract_scalar(additionalEventData, '$["x-amz-id-2"]') as s3_extended_request_id
Athena で CloudTrail ログをクエリしている、どこかの誰かにお役に立てると幸いです。
参考資料
get 'x-amz-copy-source' info from 'requestparameters' | AWS re:Post