【小ネタ】Amazon Athena で CloudTrail の S3 データイベントを拡張リクエスト ID を含めてクエリする際にハマったこと

【小ネタ】Amazon Athena で CloudTrail の S3 データイベントを拡張リクエスト ID を含めてクエリする際にハマったこと

ハイフンが含まれる JSON を抽出する際には、ドット表記法ではなく、ブラケット表記法にする必要があります。
Clock Icon2025.05.19

猫とアポロチョコが好きな 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

文字列から JSON データを抽出する - Amazon Athena

【JavaScript】ドット記法・ブラケット記法について #JavaScript - Qiita

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.