ConsoleLoginやListBucketsなどCloudTrailのグローバルなイベントをAthenaで調べてみた

2018.11.19

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

ベルリンの伊藤です。

CloudTrailが記録するConsoleLoginイベントやListBucketイベントを調査する機会があり、Athenaを使って探してみましたので、リージョンをまたいでCloudTrailイベントを探す方法をご紹介します。

グローバルイベントとリージョンイベント

マネジメントコンソールでCloudTrailを見る場合、IAMやS3のように「グローバル」ではなく、特定のリージョンが選択されます。そのため、東京リージョンで行なった操作は東京リージョンのCloudTrailイベント履歴で表示され、他のリージョンを選択するとそのイベント履歴を見ることはできません。

ではConsoleLogin (マネジメントコンソールログインイベント) やListBuckets (S3のバケット一覧取得イベント) のようにリージョンの区別がないイベントはどのリージョンのCloudTrailイベント履歴で表示されるのでしょうか。

ConsoleLoginの出力については、下記エントリでも説明されています。

CloudTrailが記録するConsoleLoginイベントについて

結論から言うと、今回の場合はドキュメントとこのブログをしっかり読んでさえいれば、Athenaまで使って探すことなくURLをちゃんと見てバージニア北部(us-east-1)のCloudTrailログを探しに行けば済むことでした。

そこのところをまず解説しますので、不要な方は読み飛ばしてください。

ConsoleLoginの出力先

ドキュメントに、以下の通り記述があります。

ほとんどのサービスの場合、イベントはアクションが発生したリージョンで記録されます。AWS Identity and Access Management (IAM)、AWS STS、Amazon CloudFront、Route 53 などのグローバルサービスの場合、イベントはグローバルサービスが含まれた任意の証跡に配信され、発生した場所は 米国東部 (バージニア北部) リージョン であるとログに記録されます。

ということで、リージョンの区別がないイベントは 米国東部 (バージニア北部) = us-east-1 に記録されます。

混乱した理由は、普段利用しているアイルランドリージョンのCloudTrailイベント履歴にもConsoleLoginが見られたためです。この原因は、上記の西澤さんのブログが解説してくれていますが、サインインイベント(ConsoleLogin)は特別でグローバルイベントとは限らないのです。

実際の動きで説明すると、IAM のページのサインイン認証情報に提示されるコンソールのサインインリンク "https://xxxxxxxxx.signin.aws.amazon.com/console" を使ってアクセスすると、自動的にus-east-1で遷移していました。これでログインすると、通常通りCloudTrailにはバージニア北部で記録されます。(ログイン後は「アイルランド」(eu-west-1)リージョンになっていましたが、これはConsoleLoginの出力先には関係ありません。)

次に、URLの「us-east-1」を「eu-west-1」に書き換えてみました。ログイン画面の見た目は変わりません。これでログインすると、ConsoleLoginはアイルランドで記録されました。

(もちろん過去のイベント履歴に関して、わざわざURLのリージョンを書き換えてログインした覚えはないので、他にもリージョンイベントとして記録されるパターンはありそうです。)


ちなみに、アイルランドリージョンからS3コンソールへ遷移すると、リージョン選択は「グローバル」ですが、URLのパラメータにeu-west-1が指定されていました: "https://s3.console.aws.amazon.com/s3/home?region=eu-west-1"
試しにパラメータを消して "https://s3.console.aws.amazon.com/s3/home" へリダイレクトすると、自動的にパラメータがus-east-1で付与されていました。

しかしこれらのListBucketsイベントは、ドキュメントに記載の通り、いずれも us-east-1 で記録されていました。


これらの確認中、実行した操作がCloudTrailイベント履歴へ思っていたよりすぐに反映されないことに気が付いたんですが、更新の反映には最大15分かかるようです。

Q: CloudTrail が API 呼び出しのイベントを送信するまで、どれくらいの時間がかかりますか?
通常、CloudTrail は、API 呼び出しから 15 分以内にイベントを送信します。

参考:よくある質問 - AWS CloudTrail | AWS

CloudWatchイベントをAthenaで分析する

ここまできてまだAthenaでの分析が必要な方は、CloudTrailイベント履歴の画面で「Amazon Athena で高度なクエリを実行します」をクリックし、言われるがままにテーブルを作成してAthenaへ移動してください。

詳細な手順やサンプルクエリは、下記ブログでとても分かりやすく説明されています。

[AWS ]CloudTrailの証跡ログをAthenaを使ってサクッと解析する[このリソース誰が作ったの?]

CloudTrailログのフォーマットはこちらのブログドキュメントでも説明されていますが、試しに「テーブルのプレビュー」を選択することで、対象テーブルの先頭10行を取得してくれ、データの中身を見ることもできます。

あとは SQL でお好きに検索するだけです。
AthenaのクエリエンジンはPrestoに基づいており、関数や演算子などの詳細はドキュメントに載っています。
ご参考に、使用した他のサンプルクエリをいくつかご紹介しておきます。

ConsoleLoginイベントで、特定日時以降の結果をイベント日時降順で取得し、上位10件のみ表示させる

useridentityの内容は階層になっているので、.usernameでユーザ名のみを取得できます。CloudTrailコンソールでのイベント日時はローカル時間になりますが、ここでの日付はUTC指定です。

SELECT eventtime,
         eventname,
         awsregion,
         useridentity.username
FROM "default"."cloudtrail_logs_cm_members_xxxxx"
WHERE eventname LIKE 'ConsoleLogin'
  AND eventtime > '2018-11-14T12:00:00Z'
ORDER BY eventtime DESC
LIMIT 10;

ListBucketsイベントで、特定日時以降でエラーとなった結果をイベント日時降順で取得し、上位10件のみ表示させる

errormessageが空でない場合を指定しています。

SELECT eventtime,
         eventname,
         awsregion,
         errormessage,
         useridentity.username
FROM "default"."cloudtrail_logs_cm_members_xxxxx"
WHERE eventname LIKE 'ListBuckets'
  AND eventtime > '2018-11-14T12:00:00Z'
  AND errormessage <> ''
ORDER BY eventtime DESC
LIMIT 10;

特定のソースIPからの特定日時以降をイベント日時降順で表示させる

SELECT eventtime,
         eventname,
         awsregion,
         errormessage,
         useridentity.username
FROM "default"."cloudtrail_logs_cm_members_xxxxx"
WHERE sourceipaddress LIKE 'xxx.xxx.xxx.xxx'
  AND eventtime > '2018-11-14T12:00:00Z'
ORDER BY eventtime DESC;

一時テーブル作成

今回、自分の操作した結果で特定日以降を手早く調査したく、毎回指定するのが面倒なので一時的に上記の最後のクエリでテーブルを作り直し、そこからSQL実行を行いました。検索対象のデータも小さくなるので、圧倒的にクエリ実行が速くなります。

実行するSQLでクエリ作成するにはもちろんCREATE TABLEするのですが、正しい構文を調べて書かずとも、コンソール上で以下のようにテーブルを作成することができました。

テーブル名や説明を指定します。プレビューでテーブル作成用SQLを確認・修正できます。

前画面で作成をクリックすると、SQLが実行され、テーブルが作成されます。

このテーブルを使って、例えば下記のように、特定日以降のソースIPにおけるエラーメッセージの一覧化がシンプルに行えます。

SELECT DISTINCT errormessage
FROM "default"."temp1";

同じように、メニューから「テーブルの削除」でDROP TABLEができます。

まとめ

今回は手っ取り早く検索する方法としてご紹介しましたが、継続して調査を行う場合にはスキャン対象(課金範囲)のデータを気にしながら実行した方が良さそうです。

リージョンまたぎがない場合には、西澤さんのブログにあるように、LOCATIONで対象年月を指定することでスキャン対象を少なく収められるようです。

その場合のSQLで、下記ブログも参考になりそうなので載せておきます。