【S3】Athena を使用して S3 のアクセスログを分析

記事タイトルとURLをコピーする

エンジョイ AWS!
サーバーワークス エンジニアの伊藤Kです。

冬。温かい飲み物と、ケーキが美味しい季節です。

最近、 この記事 でS3のサーバーアクセスログを見る機会がありましたが、
S3のサーバーアクセスログは、ログが出力されるS3のバケット内に、1行が横に長いテキスト、かつ複数のファイルに分かれて取られているので、
中身を見るために一つ一つダウンロードし、検索する、などが手間。

S3に格納されたログデータを扱うならAthenaはどうか?ということで調べたところ、AWS公式ドキュメントにも方法が紹介されていました。
それに沿って、Athenaを使ってログを分析してみます。

そもそも、S3のアクセスログの取り方

  • アクセスログが格納される先のS3のバケット(ターゲットバケット)を作成します。マネジメントコンソールからであれば、デフォルトの設定で作成して問題ありません(2021年1月8日現在)
    • 今回は、「swx-k-ito-s3log」というバケット名で作成しました
  • ログを取りたいバケット(ソースバケット)で「サーバーアクセスのログ記録」を有効にする設定を行います。デフォルトは無効です
    • 手順は 公式のドキュメント の説明で迷いなく設定可能と思いますので、ここでは省略します
    • 1点だけ注意点として、下図の通りマネジメントコンソールの「ターゲットバケット」の形式説明が「s3://bucket/prefix」となっている(2021年1月8日現在)のですが、Athenaで分析することを考えると、「s3://bucket/prefix/」(末尾にスラッシュを入れる)がお勧めです

f:id:swx-kenichi-ito:20210110221131p:plain

  • ソースバケットへ、APIリクエストによるアクセスがあると、ターゲットバケットに、prefix名のフォルダが作成され、その中にログが格納されていきます

f:id:swx-kenichi-ito:20210110221148p:plain

  • ログの詳細な形式や出力されるまでの時間については こちらの公式ドキュメント をご参照ください。「ベストエフォート型のサーバーログ配信」ということで、けっこうクセがあります

Athenaを使ってログを分析

それでは本題です。
以下、 公式のドキュメント に沿って作業を進めていきます。


マネジメントコンソールからAthenaを開いて、「クエリエディタ」で以下のクエリを実行します。

create database s3_access_logs_db

f:id:swx-kenichi-ito:20210110221209p:plain

左ペインの「データベース」プルダウンから作成したデータベースを選択した後、以下のクエリを実行して、データベースにテーブルスキーマを作成します。

  • 最終行の「LOCATION」では、「サーバーアクセスのログ記録」の設定時に指定した、S3 バケットおよびプレフィックスのパスを入力します。公式ドキュメントの説明にあるように、プレフィックスの最後にスラッシュ (/) を含めるようにしてください。(ここで、上記の「1点だけ注意点として~」が生きてきます)
CREATE EXTERNAL TABLE IF NOT EXISTS s3_access_logs_db.mybucket_logs(
         BucketOwner STRING,
         Bucket STRING,
         RequestDateTime STRING,
         RemoteIP STRING,
         Requester STRING,
         RequestID STRING,
         Operation STRING,
         Key STRING,
         RequestURI_operation STRING,
         RequestURI_key STRING,
         RequestURI_httpProtoversion 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 (
         'serialization.format' = '1', 'input.regex' = '([^ ]*) ([^ ]*) \\[(.*?)\\] ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) \\\"([^ ]*) ([^ ]*) (- |[^ ]*)\\\" (-|[0-9]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) (\"[^\"]*\") ([^ ]*)(?: ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*))?.*$' )
LOCATION 's3://swx-k-ito-s3log/testlogs/'

f:id:swx-kenichi-ito:20210110221230p:plain

このテーブルスキーマの各項目が、S3のアクセスログのスペースで区切られているレコード各項目と対応しています。
SQL文を知っていると、何となく感覚はつかめます。

左のペインの「テーブル」で、テーブル名の横にある縦3点をクリックし、「テーブルのプレビュー」を選択します。

f:id:swx-kenichi-ito:20210110221321p:plain

「結果」ウィンドウに、サーバーのアクセスログからのデータ (bucketowner、bucket、requestdatetime など) が表示されれば、正常にテーブルが作成されています。

f:id:swx-kenichi-ito:20210110221336p:plain

後は、公式ドキュメントの例にあるように、SQL文を発行して結果を見ることで、効率的に検索や値の抽出ができる、はずだったのですが・・・

Deleteにまつわるエトセトラ

公式ドキュメントの例から、「key」に対象のオブジェクト名が載ってくるようなので、
前回記事の通り、Cyberduckを使用してファイルのアップロード、コピー、削除を実行した後、ログを見てみます。
「ベストエフォート型のログ」なので、実行して2時間ぐらい間を開けてから確認。

こんなクエリにします。(ファイル名003.pngが、履歴を追いたいファイルのパスとします。)

SELECT * FROM s3_access_logs_db.mybucket_logs WHERE key = '003.png';

結果
f:id:swx-kenichi-ito:20210110221447p:plain

あれ、削除が載ってこない。
そこで、今度はどのオブジェクトでもよいので削除を見てみよう、と、
公式ドキュメントの例にあるこのクエリを実行します。

SELECT * FROM s3_access_logs_db.mybucket_logs WHERE operation like '%DELETE%';

結果
f:id:swx-kenichi-ito:20210110221513p:plain

keyは「-」で、requesturi_keyは「/?delete」。
レコードの全項目を見てみますが、ファイル名が分かるような記載がどこにもない・・・

この後、以下の通りいろいろと試してみるも、レコードの内容は変わらず。

  • Cyberduckの削除リクエストの形式が原因か、とオブジェクトをマネジメントコンソールから削除してみる
  • 「ベストエフォート型のログ」で載らないこともある、との記載が公式ドキュメントにあったので、ファイルを変えたりして何度か繰り返す
  • Athenaのテーブルを作り直す

などなど・・・

手詰まりとなり、上記公式ドキュメントに「詳しくは、高井の動画をご覧ください」のリンクがあったのでそれを見てみると、
高井さんの動画で抽出されたレコードは
 operation:REST.DELETE.OBJECT
 key:削除したオブジェクト名
上図の実行結果は
 operation:REST.POST.MULTI_OBJECT_DELETE
 key:"-"
なので、出力のされかたに差異があります。

サポートへ問い合わせたところ、削除時に使われているAPIが違っており、
MULTI_OBJECT_DELETEの場合は、S3アクセスログにオブジェクトキーが出力されない仕様とのこと。
そして、現状では、S3コンソールからオブジェクトを削除する場合は、MULTI_OBJECT_DELETEが使用されるとのことでした。
Cyberduckで使用しているAPIもMULTI_OBJECT_DELETEと思われます。

削除リクエストに使用しているAPIの形式によって、オブジェクト名はログに載ってこないことは、注意が必要です。


それでは、楽しいAWSライフを!
f:id:swx-kenichi-ito:20210108135211p:plain

伊藤K (記事一覧)

おっさんエンジニア。

甘いお菓子が大好きですが、体重にDirect Connectなので控えています。

「エンジョイ AWS」を合言葉に、AWSを楽しむことを心がけています。