AWS Athenaを使ってCloudTrailのログを自分で設定した項目について解析したメモ


前提

Athenaのこと、きちんと理解できていないかもしれません。以下の記述はその場しのぎでうまくいっただけの可能性があります。

やりたいこと

CloudTrailのログを必要な項目だけで解析したい。

最初にやってうまくいかなかった方法

ColudTrailのイベント履歴からAmazon Athena で高度なクエリを実行しますで自動作成されるAthenaのテーブルは、自分で項目を追加することができませんでした。

CREATE EXTERNAL TABLE [TABLE_NAME] (
    eventVersion STRING,
    userIdentity STRUCT<
        type: STRING,
        principalId: STRING,
        arn: STRING,
        accountId: STRING,
        invokedBy: STRING,
        accessKeyId: STRING,
        userName: STRING,
        sessionContext: STRUCT<
            attributes: STRUCT<
           (中略)
    sharedEventID STRING,
    vpcEndpointId STRING
)
COMMENT 'CloudTrail table for [S3_BUCKET_NAME] bucket'
ROW FORMAT SERDE 'com.amazon.emr.hive.serde.CloudTrailSerde'
STORED AS INPUTFORMAT 'com.amazon.emr.cloudtrail.CloudTrailInputFormat'
OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION '[S3_BUCKET_URL]'
TBLPROPERTIES ('classification'='cloudtrail');

ここで指定している項目(例えば userIdentity.type など)以外は、いくら上記のCREATE TABLEの内容をコピペしてAthenaで直接必要な項目を追加してテーブルを作成しても、クエリ(SELECT)時にその追加した項目を指定すると構文エラーが起こってしまいました。

どうも ROW FORMAT SERDE 'com.amazon.emr.hive.serde.CloudTrailSerde'でSerDeをCloudTrailSerdeを指定すると、デフォルトの項目しかシリアライズ・でシリアライズしてくれないもようでした。

うまくいった方法

以下の記事を見つけて解決

CloudTrailログからAmazon Athenaを使ってログイン監査レポートを作成する

こちらの記事では、SerDeをROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'を指定し、CloudTrailのログJSONファイルのから取得していました。

上記記事より引用
CREATE EXTERNAL TABLE IF NOT EXISTS records_201702 (
  records ARRAY<
    STRUCT<
      eventTime:STRING,
      eventSource:STRING,
      eventName:STRING,
      awsRegion:STRING,
      sourceIPAddress:STRING,
      userIdentity:STRUCT<
        type:STRING,
        arn:STRING
      >
    >
  >
)
ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'
LOCATION 's3://[CloudTrailログ出力バケット名]/[prefix指定があれば]/AWSLogs/[AWSアカウントID]/CloudTrail/[Region]/2017/02';

こうしたらうまくいきました!

ちなみにクエリーは、records[]に複数含まれるSTRUCTを取得する必要があるので、以下のようになります。

SELECT \
  record.eventTime, \
  record.eventName, \
  record.userIdentity.type, \
  FROM JOIN UNNEST(records) AS t (record) \
WHERE record.eventName = 'GetObject' \
LIMIT 10;

上記はS3のGetObjectイベントだけ10件取得するクエリーです。

最後に

Athenaのことをきちんと理解できていれば、もっとスマートなやり方がある
のかもしれません。もし記述した内容に間違いがあればすぐ訂正いたしますので、ご指摘いただければ嬉しいです。