Amazon Athena CloudTrailSerdeを利用してAWSのアクティビティを探索する

eyecatch_athena

7/1(土)開催のDevelopers.IO 2017 では「現場で使える Amazon Athena」と題して、私がハンズオンセミナーを担当することになりました。Amazon Athena はビックデータだけでなくAWSを利用する全ての人々に有益なサービスです!今日はハンズオンでも紹介したい『CloudTrailSerde』を解説します。

『CloudTrailSerde』とは

『CloudTrailSerde』とは、CloudTrail のログファイルをパースして Athena テーブルを作成できるデシリアライザーです。つまり、これを利用することでこれまでより簡単かつ高速に CloudTrail のログファイルをクエリできるようになります。

すでに弊社の西澤さんが同じようなブログをご紹介しています。このブログは jsonファイルである CloudTrailのログファイルを JsonSerDe と 「CROSS JOIN UNNEST」構文を利用してレポート出力しています。後述の「『CloudTrailSerde』の制限事項」で解説しているとおり、このアプローチは現在でも有効であることは変わりません。

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

その後 CloudTrail のログファイルをデシリアライズする専用の『CloudTrailSerde』が Amazon Athena サポートされました。

Analyze Security, Compliance, and Operational Activity Using AWS CloudTrail and Amazon Athena

『CloudTrailSerde』を使ってテーブル作成

Anazon Athena や Hadoop(Hive)を使ったことがない人がこれを見ると、この時点で諦めてしまうかもしれませんが、テーブル名cloudtrail_logsと CloudTrail のログのパスs3://<バケット名>/AWSLogs/123456789012/CloudTrail/us-east-1/2017/05/を皆さんの環境に合わせて、変更してテーブルを作成するだけでOKです。

CloudTrail のログのパスは、検索の対象としたい期間に応じてパスを指定します。例えば、

  • 2017年5月1日の場合:s3://<バケット名>/AWSLogs/123456789012/CloudTrail/us-east-1/2017/05/01/
  • 2017年5月の場合:s3://<バケット名>/AWSLogs/123456789012/CloudTrail/us-east-1/2017/05/

※ 毎回全てのログファイルをスキャンするので、検索の対象の期間を大きくしてしまうと期間に比例してAWS利用費が発生しますのでご注意ください。なお、利用費は1TBあたり$5、リージョン間転送は別料金です。

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>>>,
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 BOOLEAN,
recipientAccountId STRING,
serviceEventDetails STRING,
sharedEventID STRING,
vpcEndpointId STRING
)
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://cloudtrail-us-east-1-123456789012/AWSLogs/123456789012/CloudTrail/us-east-1/2017/05/';

カラムについては CloudTrail Record Contents を御覧ください。

なお、このDDLの構文を理解したい方は、以前書いたブログ Amazon Athena Nested-JSONのSESログファイルを検索する をご覧下さい。

AWSのアクティビティを探索する

では、早速 AWS のアクティビティを探索しましょう!

一日のアクティビティ数と一覧を取得する

最初にアクティビティ数を取得します。

select count(*) as activity_count 
from cloudtrail_logs
where eventtime >= '2017-05-18T00:00:00Z' and eventtime < '2017-05-19T00:00:00Z';

20170518-cloudtrailserde-1

続いて、アクティビティ一覧を取得します。

select eventname, useridentity.username, sourceIPAddress, eventtime 
from cloudtrail_logs
where eventtime >= '2017-05-18T00:00:00Z' and eventtime < '2017-05-19T00:00:00Z'
order by eventtime asc;

20170518-cloudtrailserde-2

以降では、このようにCloudTrailのログは eventname と eventtime をキーにアクティビティを調べます。

マネジメントコンソールへのログイン一覧を取得する

「利用者不明なIAMアカウントがある!マネジメントコンソールへのログインされたかを確認したい!」そんなときに役に立ちそうです。(そんなことあってはならないのですが...)

select useridentity.username, sourceIpAddress, eventtime, additionaleventdata
from cloudtrail_logs
where eventname = 'ConsoleLogin'
and eventtime >= '2017-05-17T00:00:00Z'
and eventtime < '2017-05-18T00:00:00Z';

20170518-cloudtrailserde-3

Security Group 変更の監査する

「ネットワークが接続できない?いつ変更されたかを確認したい!」といったときに Security Group が 誰がいつ変更したのかを確認することができます。以下の例では、全ての Security Group を監査の対象とするため、条件にrequestparameters like '%sg-%'と指定しています。 今回はAthenaのクエリーの実行がヒットしないようにするためeventname <> 'StartQueryExecution'と条件指定して除外しています。

select eventname, useridentity.username, sourceIPAddress, eventtime, requestparameters 
from cloudtrail_logs
where requestparameters like '%sg-%'
and eventtime >= '2017-05-18T00:00:00Z' 
and eventtime < '2017-05-19T00:00:00Z'
and eventname <> 'StartQueryExecution'
order by eventtime asc;

20170518-cloudtrailserde-4

上記は 「Security Group 変更」がテーマでしたが、他のリソースIDのプレフィックスを指定することで様々なアクティビティが監査できます。

AWSのイベントエラーの監査

問題が顕在化してから調査に着手するのではなく、定期的なエラーやその発生頻度などを把握して、不正アクセスやサービス品質の低下の兆候を把握することが求められます。以下のクエリーでは、1ヶ月間に発生したエラーのTop10を一覧表示します。

select count (*) as TotalEvents, eventname, errorcode, errormessage 
from cloudtrail_logs
where errorcode is not null
and eventtime >= '2017-05-01T00:00:00Z' 
group by eventname, errorcode, errormessage
order by TotalEvents desc
limit 10;

20170518-cloudtrailserde-5

『CloudTrailSerde』の制限事項

『CloudTrailSerde』を利用することで、簡単にCloudTrailのログに対してクエリーが実行できるようになりましたが、一部のカラムは、サービスに依存する可変データ形式を持つ文字列値のため、カラムのように参照することがき出ません。以下のカラムを参照する必要がある場合は、データパターンを特定し、OpenXJSONSerDeなどの別のSerDeを使用してjsonファイルを参照する必要があります。

  • requestParameters
  • responseElements
  • additionalEventData
  • serviceEventDetails

上記のカラムデータは、json形式のまま出力されますが参照できないわけではありません。json形式の文字列を参照したり、条件指定したりも可能です。

まとめ

最初はCloudTrailの『CloudTrailSerde』のブログなんて地味な内容だと思っていましたが、書いているうちに再発見があり楽しくなってきました。

弊社のメンバースに加入のAWS環境は、デフォルトで全てのリージョンのCloudTrailが有効に設定され、監査ログが出力されていますので、ぜひお試しいただくことをおすすめします。