Amazon Athena S3のサーバアクセスログでS3署名バージョンを確認してみた
APIリクエストの署名バージョンなどの確認が可能になったAmazon S3のサーバアクセスログをAmazon Athenaで確認する方法をご紹介します。Amazon Athenaを用いることで複数のファイルの検索もSQL文で横断的に検索が可能です。SigV4で通信できているかどうかを10分程度で確認できる手順を解説します。
当初はCloudTrailの監査ログから確認しようと思いましたが、デフォルトでは署名バージョンに関する項目が出力されません。監査ログという特性上、気軽に設定変更するのを躊躇していたところ弊社のすずきさんがS3のサーバアクセスログで署名バージョンの確認ができるようになりましたというブログで署名バージョンを確認する方法を紹介していました。S3のサーバアクセスログは複数ファイルにまたがるため、私はそれをAmazon Athenaで確認することにしました。
確認したいことは
- 確認対象のサーバーのAWSCLIが、SigV4で送信できているか?
- => 送信元IPアドレスで確認したい
- ファイルを送信しているアプリが、SigV4で送信できているか?
- => 使っているSDKやバージョン、アプリを確認したい
- 確認したサーバアクセスログを提出したい
- => 確認したSigV4のサーバアクセスログのファイルを特定したい
などです。更にマネジメントコンソールからのS3アクセスは除外したい。S3のサーバアクセスログとAmazon Athenaを用いれば簡単に確認できます。
確認対象のS3バケットcm-app-dataとS3のサーバアクセスログ保存先のS3バケットcm-app-data-s3accesslogを用意しました。
手順 1 : Amazon S3のサーバアクセスログの設定
S3のサーバアクセスログの設定は、確認対象のS3バケットcm-app-dataの[プロパティ]タブの[サーバーアクセスのログ記録]をクリックして、以下のダイアログボックスの「ターゲットバケット」に、S3のサーバアクセスログ保存先のS3バケットcm-app-data-s3accesslogを指定します。
ログは大体1時間ぐらい遅れて出力されますので、S3バケットにファイルを出力して一時間ほど放置してください。
手順 2 : Amazon Athenaにテーブルを作成
何も考えずに、32行目のS3のサーバアクセスログの保存先のS3バケットを指定してテーブルを作成してください。
-- DROP TABLE s3_server_accesslog; CREATE EXTERNAL TABLE IF NOT EXISTS s3_server_accesslog ( bucket_owner string, bucket string, time string, remote_ip string, requester string, request_id string, operation string, request_uri string, http_status string, error_code string, bytes_sent string, object_size string, total_time string, turn_around_time string, referrer string, col16 string, user_agent string, version_id string, host_id string, signature_version string, cipher_suite string, authentication_type string, host_header string, tls_version string ) ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.RegexSerDe' WITH SERDEPROPERTIES ( 'serialization.format' = '1', 'input.regex'='(\\S+) (\\S+) (\\S+ \\S+) (\\S+) (\\S+) (\\S+) (\\S+) (\\S+) (\\"[^\\"]*\\") (\\S+) (\\S+) (\\S+) (\\S+) (\\S+) (\\S+) (\\"[^\\"]*\\") (\\"[^\\"]*\\") (\\S+) (\\S+) (\\S+) (\\S+) (\\S+) (\\S+) (\\S+)' ) LOCATION 's3://<S3のサーバアクセスログ保存先のS3バケット>/' TBLPROPERTIES ('has_encrypted_data'='false');
カラム名は、Amazon S3 Server Access Log Formatを参考にカラム指定しました。16番目のカラムはマニュアルにも記載がありませんでしたので、col16という名前を指定しています。なお、S3のサーバアクセスログのパースには、RegexSerDeを用いています。
上記のDDLを実行すると「クエリは成功しました」と表示されます。
手順 3 : S3のサーバアクセスログをザックリ検索
まずは以下のクエリを実行してどんな内容が参照できるか、ザックリ内容を把握します。S3のサーバアクセスログが出力されているのに、ここでログが表示できなければ、手順1や手順2を再確認してください。以下では、必要なカラムに限定して表示しています。
SELECT time, signature_version, bucket, remote_ip, requester, operation, request_uri, http_status, error_code, user_agent, "$path" AS s3path FROM s3_server_accesslog ORDER BY 1 limit 100 -- ザックリ前頭の100行 ;
実行結果は以下のとおりです。
上記のダウンロードアイコン(結果右のバインダーのような水色のアイコン)をクリックすると、結果をCSVファイル形式でダウンロードできます。ダウンロードした内容は以下のとおりです。signature_versionカラムに署名バージョンがSigV4
であることが確認できます。remote_ipは送信元のIPアドレス、bucketはS3バケット、user_agentは送信したアプリやライブラリとそのバージョンまで確認できます。そして、最後のs3pathカラムは、S3のサーバアクセスログを出力しています。
"time","signature_version","bucket","remote_ip","requester","operation","request_uri","http_status","error_code","user_agent","s3path" "[06/Jun/2019:10:59:56 +0000]","SigV4","cm-app-data","124.144.28.33","arn:aws:sts::1234567890123:assumed-role/cm-user/cm-user","REST.PUT.LOGGING_STATUS","-","""PUT /cm-app-data?logging= HTTP/1.1""","200","""S3Console/0.4, aws-internal/3 aws-sdk-java/1.11.526 Linux/4.9.137-0.1.ac.218.74.329.metal1.x86_64 OpenJDK_64-Bit_Server_VM/25.202-b08 java/1.8.0_202 vendor/Oracle_Corporation""","s3://cm-app-data-s3accesslog/2019-06-06-11-48-07-14DA17173B55A6D4" "[06/Jun/2019:11:05:07 +0000]","SigV4","cm-app-data","124.144.28.33","arn:aws:sts::1234567890123:assumed-role/cm-user/cm-user","REST.HEAD.BUCKET","-","""HEAD /cm-app-data HTTP/1.1""","200","""S3Console/0.4, aws-internal/3 aws-sdk-java/1.11.526 Linux/4.9.137-0.1.ac.218.74.329.metal1.x86_64 OpenJDK_64-Bit_Server_VM/25.202-b08 java/1.8.0_202 vendor/Oracle_Corporation""","s3://cm-app-data-s3accesslog/2019-06-06-12-19-32-805F2AB546971E57" : :
手順 4 : S3のサーバアクセスログからSigV4の確認
上記のままでは大量のレコードが表示されますので、以下のように条件を絞って目的のログを探します。
- S3Consoleのリクエストは除く
- 署名バージョンは
SigV4
のみ表示 - 送信元IPアドレスを指定
- 確認したいバケットを指定
SELECT time, signature_version, bucket, remote_ip, requester, operation, request_uri, http_status, error_code, user_agent, "$path" AS s3path FROM s3_server_accesslog WHERE NOT regexp_like(user_agent, '.*S3Console.*') -- S3Consoleからのリクエストは除外 AND signature_version = 'SigV4' -- SigV4 AND remote_ip = '124.144.28.33' -- 送信元IPアドレス AND bucket = 'cm-app-data' -- 確認したいバケット ORDER BY 1 ;
下記の通り、確認したいログをピンポイントで参照できるはずです。最後のs3pathカラムは、S3のサーバアクセスログを出力しています。署名バージョンがSigV4
対応であることのエビデンスはこのファイルを提出すればOKです。
まとめ
署名バージョンSigV4
対応の確認方法は様々ありますが、既存の対応状況を数日に渡って確認したり、複数のクライアント(boto,boto3,JavaのAWS SDK等)や複数のS3バケットをまとめて確認したいという要件があり、最終的にAmazon Athenaを用いる方法に至りました。S3のサーバアクセスログ保存先のS3バケットはライフサイクル設定でクリーンナップするように設定すれば安心してご利用いただけるはずです。2019/06/24の期限に迫った現在、最終確認にご利用ください。