Athena を使用して Amazon S3 サーバーのアクセスログを分析するにはどうすればよいですか?

最終更新日:2021-12-17

Amazon Athena で Amazon Simple Storage Service (Amazon S3) サーバーのアクセスログをクエリするにはどうすればよいですか?

解決方法

Amazon S3 は、サーバーのアクセスログを S3 バケット内のオブジェクトとして保存します。Athena を使用すると、サーバーアクセスログの分析またはクエリがすばやく行えます。

1.   既に行っていない場合は、S3 バケットのサーバーアクセスのログ記録をオンにします。[Target bucket] (ターゲットバケット) と [Target prefix] (ターゲットプレフィックス) の値を書き留めます。Athena クエリで Amazon S3 の場所を指定するときに必要になります。

2.    Amazon Athena コンソールを開きます。

3.    クエリエディタで、DDL 文を実行してデータベースを作成します。
注意: ベストプラクティスとして、データベースは、S3 バケットと同じ AWS リージョンで作成することをお勧めします。

create database s3_access_logs_db

4.    データベースにテーブルスキーマを作成します。次の例では、STRING および BIGINT データ型の値は、アクセスログのプロパティです。これらのプロパティは Athena でクエリできます。LOCATION では、ステップ 1 で書き留めた S3 バケットおよびプレフィックスのパスを入力します。プレフィックスの最後にスラッシュ (/) を含めるようにしてください (例: s3://doc-example-bucket/prefix/)。プレフィックスを使用しない場合は、バケット名の最後にスラッシュ (/) を含めます (例: s3: //doc-example-bucket/)。

CREATE EXTERNAL TABLE `s3_access_logs_db.mybucket_logs`(
  `bucketowner` STRING,
  `bucket_name` STRING,
  `requestdatetime` STRING,
  `remoteip` STRING,
  `requester` STRING,
  `requestid` STRING,
  `operation` STRING,
  `key` STRING,
  `request_uri` STRING,
  `httpstatus` STRING,
  `errorcode` STRING,
  `bytessent` BIGINT,
  `objectsize` BIGINT,
  `totaltime` STRING,
  `turnaroundtime` STRING,
  `referrer` STRING,
  `useragent` STRING,
  `versionid` STRING,
  `hostid` STRING,
  `sigv` STRING,
  `ciphersuite` STRING,
  `authtype` STRING,
  `endpoint` STRING,
  `tlsversion` STRING)
ROW FORMAT SERDE
  'org.apache.hadoop.hive.serde2.RegexSerDe'
WITH SERDEPROPERTIES (
  'input.regex'='([^ ]*) ([^ ]*) \\[(.*?)\\] ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) (\"[^\"]*\"|-) (-|[0-9]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) (\"[^\"]*\"|-) ([^ ]*)(?: ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*))?.*$')
STORED AS INPUTFORMAT
  'org.apache.hadoop.mapred.TextInputFormat'
OUTPUTFORMAT
  'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION
  's3://awsexamplebucket1-logs/prefix/'

5.    左側のペインの [Tables] (テーブル) で、テーブル名の横にあるメニューボタンから [Preview table] (テーブルのプレビュー) を選択します。[Results] (結果) ウィンドウに、サーバーのアクセスログからのデータ (bucketownerbucketrequestdatetime など) が表示される場合、Athena テーブルは正しく作成されています。これで Amazon S3 サーバーアクセスログのクエリを実行できます。

クエリの例

削除済みオブジェクトのリクエストを検索するには、次のクエリを使用します:

SELECT * FROM s3_access_logs_db.mybucket_logs WHERE
key = 'images/picture.jpg' AND operation like '%DELETE%';

403 Access Denied エラーが発生したリクエストの Amazon S3リクエスト ID を表示するには、次のクエリを使用します:

SELECT requestdatetime, requester, operation, requestid, hostid FROM s3_access_logs_db.mybucket_logs
WHERE httpstatus = '403';

特定の期間における HTTP 5xx エラー (キーとエラーコードを含む) の Amazon S3 リクエスト ID を見つけるには、次のクエリを実行します:

SELECT requestdatetime, key, httpstatus, errorcode, requestid, hostid FROM s3_access_logs_db.mybucket_logs
WHERE httpstatus like '5%' AND
parse_datetime(requestdatetime,'dd/MMM/yyyy:HH:mm:ss Z')
BETWEEN parse_datetime('2021-09-18:07:00:00','yyyy-MM-dd:HH:mm:ss')
AND
parse_datetime('2021-09-18:08:00:00','yyyy-MM-dd:HH:mm:ss');

タイムスタンプ、IPアドレス、AWS Identity and Access Management(IAM)ロールなど、誰がいつオブジェクトを削除したかを表示するには、次のクエリを使用します:

SELECT requestdatetime, remoteip, requester, key FROM s3_access_logs_db.mybucket_logs WHERE
key = 'images/picture.jpg' AND operation like '%DELETE%';

IAM ロールによって実行されたすべてのオペレーションを表示するには、次のクエリを使用します:

SELECT * FROM s3_access_logs_db.mybucket_logs WHERE
requester='arn:aws:iam::123456789123:user/user_name';

指定された期間にオブジェクトに対して実行されたすべてのオペレーションを表示するには、次のクエリを使用します:

SELECT SUM(bytessent) as uploadtotal,
SUM(objectsize) as downloadtotal,
SUM(bytessent + objectsize) AS total FROM s3_access_logs_db.mybucket_logs
WHERE remoteIP='1.2.3.4' AND 
parse_datetime(requestdatetime,'dd/MMM/yyyy:HH:mm:ss Z')
BETWEEN parse_datetime('2021-07-01','yyyy-MM-dd')
AND parse_datetime('2021-08-01','yyyy-MM-dd');

特定の期間に IP アドレスを介して転送されたデータの量を表示するには、次のクエリを使用します:

SELECT SUM(bytessent) as uploadtotal,
SUM(objectsize) as downloadtotal,
SUM(bytessent + objectsize) AS total FROM s3_access_logs_db.mybucket_logs
WHERE remoteIP='1.2.3.4' AND 
parse_datetime(requestdatetime,'dd/MMM/yyyy:HH:mm:ss Z')
BETWEEN parse_datetime('2021-07-01','yyyy-MM-dd')
AND parse_datetime('2021-08-01','yyyy-MM-dd');

特定の期間にライフサイクルルールによって実行されたすべての期限切れオペレーションを表示するには、次のクエリを使用します:

SELECT *
FROM s3_access_logs_db.mybucket_logs
WHERE operation = 'S3.EXPIRE.OBJECT' AND
parse_datetime(requestdatetime,'dd/MMM/yyyy:HH:mm:ss Z')
BETWEEN parse_datetime('2021-09-18:00:00:00','yyyy-MM-dd:HH:mm:ss')
AND
parse_datetime('2021-09-19:00:00:00','yyyy-MM-dd:HH:mm:ss');

特定の期間に期限切れになったオブジェクトの数をカウントするには、次のクエリを使用します:

SELECT count(*) as ExpireCount
FROM s3_access_logs_db.mybucket_logs
WHERE operation = 'S3.EXPIRE.OBJECT' AND
parse_datetime(requestdatetime,'dd/MMM/yyyy:HH:mm:ss Z')
BETWEEN parse_datetime('2021-09-18:00:00:00','yyyy-MM-dd:HH:mm:ss')
AND
parse_datetime('2021-09-19:00:00:00','yyyy-MM-dd:HH:mm:ss');

特定の期間にライフサイクルルールによって実行されたすべての移行オペレーションを表示するには、次のクエリを使用します:

SELECT * FROM s3_access_logs_db.mybucket_logs
WHERE operation like 'S3.TRANSITION%' AND
parse_datetime(requestdatetime,'dd/MMM/yyyy:HH:mm:ss Z')
BETWEEN parse_datetime('2021-09-18:00:00:00','yyyy-MM-dd:HH:mm:ss')
AND
parse_datetime('2021-09-19:00:00:00','yyyy-MM-dd:HH:mm:ss');

すべてのリクエスタを署名バージョンごとにグループ化して表示するには、次のクエリを使用します:

SELECT requester, Sigv, Count(Sigv) as SigCount
FROM s3_access_logs_db.mybucket_logs
GROUP BY requester, Sigv;

特定の期間にリクエストを行っている匿名リクエスタをすべて表示するには、次のクエリを使用します:

SELECT Bucket, Requester, RemoteIP, Key, HTTPStatus, ErrorCode, RequestDateTime
FROM s3_access_logs_db.mybucket_logs
WHERE Requester IS NULL AND
parse_datetime(RequestDateTime,'dd/MMM/yyyy:HH:mm:ss Z')
BETWEEN parse_datetime('2021-07-01:00:42:42','yyyy-MM-dd:HH:mm:ss')
AND
parse_datetime('2021-07-02:00:42:42','yyyy-MM-dd:HH:mm:ss')

特定の期間内に PUT オブジェクトリクエストを送信しているすべてのリクエスタを表示するには、次のクエリを使用します:

SELECT Bucket, Requester, RemoteIP, Key, HTTPStatus, ErrorCode, RequestDateTime
FROM s3_access_logs_db
WHERE Operation='REST.PUT.OBJECT' AND
parse_datetime(RequestDateTime,'dd/MMM/yyyy:HH:mm:ss Z')
BETWEEN parse_datetime('2021-07-01:00:42:42','yyyy-MM-dd:HH:mm:ss')
AND
parse_datetime('2021-07-02:00:42:42','yyyy-MM-dd:HH:mm:ss')

特定の期間に GET オブジェクトリクエストを送信しているすべてのリクエスタを表示するには、次のクエリを使用します。

SELECT Bucket, Requester, RemoteIP, Key, HTTPStatus, ErrorCode, RequestDateTime
FROM s3_access_logs_db
WHERE Operation='REST.GET.OBJECT' AND
parse_datetime(RequestDateTime,'dd/MMM/yyyy:HH:mm:ss Z')
BETWEEN parse_datetime('2021-07-01:00:42:42','yyyy-MM-dd:HH:mm:ss')
AND
parse_datetime('2021-07-02:00:42:42','yyyy-MM-dd:HH:mm:ss')

特定の期間にリクエストを行っている匿名リクエスタをすべて表示するには、次のクエリを使用します:

SELECT Bucket, Requester, RemoteIP, Key, HTTPStatus, ErrorCode, RequestDateTime
FROM s3_access_logs_db.mybucket_logs
WHERE Requester IS NULL AND
parse_datetime(RequestDateTime,'dd/MMM/yyyy:HH:mm:ss Z')
BETWEEN parse_datetime('2021-07-01:00:42:42','yyyy-MM-dd:HH:mm:ss')
AND
parse_datetime('2021-07-02:00:42:42','yyyy-MM-dd:HH:mm:ss')

すべてのリクエスタを (特定の期間で最も高いターンアラウンドタイム順に並べて) 表示するには、次のクエリを使用します:

SELECT * FROM s3_access_logs_db.mybucket_logs
NOT turnaroundtime='-' AND
parse_datetime(requestdatetime,'dd/MMM/yyyy:HH:mm:ss Z')
BETWEEN parse_datetime('2021-09-18:00:00:00','yyyy-MM-dd:HH:mm:ss')
AND
parse_datetime('2021-09-19:00:00:00','yyyy-MM-dd:HH:mm:ss')
ORDER BY CAST(turnaroundtime AS INT) DESC;

ベストプラクティスとして、サーバーのアクセスログバケットに対してライフサイクルポリシーを作成することをお勧めします。ライフサイクルポリシーを設定して、定期的にログファイルを削除します。これにより、各クエリで Athena が分析するデータの量が減ります。