AWS CLI を用いて S3 サーバーアクセスログを有効化してみた

2024.06.26

はじめに

猫とアポロチョコが好きな、アノテーション株式会社の m.hayakawa です。

S3 サーバーアクセスログに関する検証を行うことが多いのですが、毎回やり方を忘れてしまうため、手順を記事化します。

せっかくなので、今回は AWS CLI を用いて S3 サーバーアクセスログを有効化する方法について記載します。

流れを知りたい方の一助になれば幸いです。

なお、Athena でクエリする方法についても、後日記事化する予定です。

事前準備

S3 バケット

ログ取得対象の S3 バケット:source-bucket-test0123

ログ保存先の S3 バケット:logging-bucket-test0123

AWS CLI に指定するファイル

ログ保存先 S3 バケットに設定するバケットポリシーをファイルとして保存します。

※SOURCE-ACCOUNT-ID はお使いのアカウント ID に置き換えてください。

policy.json

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "S3ServerAccessLogsPolicy",
            "Effect": "Allow",
            "Principal": {
                "Service": "logging.s3.amazonaws.com"
            },
            "Action": [
                "s3:PutObject"
            ],
            "Resource": "arn:aws:s3:::logging-bucket-test0123/*",
            "Condition": {
                "ArnLike": {
                    "aws:SourceArn": "arn:aws:s3:::source-bucket-test0123"
                },
                "StringEquals": {
                    "aws:SourceAccount": "SOURCE-ACCOUNT-ID"
                }
            }
        }
    ]
}

ログの保存先の設定をファイルとして保存します。

※TargetPrefix は何でもいいですが、どのバケットから出力されたかを識別するために、ログ取得対象の S3 バケット名を指定しています。

logging.json

{
   "LoggingEnabled": {
       "TargetBucket": "logging-bucket-test0123",
       "TargetPrefix": "source-bucket-test0123/"
    }
}

やってみた

S3 バケットの作成

ログ取得対象の S3 バケットとログ保存先の S3 バケットを作成します。

$ aws s3api create-bucket --bucket source-bucket-test0123 --create-bucket-configuration LocationConstraint=ap-northeast-1                                                                                           
{
    "Location": "http://source-bucket-test0123.s3.amazonaws.com/"
}
$ aws s3api create-bucket --bucket logging-bucket-test0123 --create-bucket-configuration LocationConstraint=ap-northeast-1                                                                                          
{
    "Location": "http://logging-bucket-test0123.s3.amazonaws.com/"
}

どちらもバケット ACL は無効(推奨)にしています。

ログ保存先の S3 バケットにバケットポリシーを付与

$ aws s3api put-bucket-policy --bucket logging-bucket-test0123 --policy file://policy.json

ログ取得対象の S3 バケットの S3 サーバーアクセスログを有効化する

$ aws s3api put-bucket-logging --bucket source-bucket-test0123 --bucket-logging-status file://logging.json

ログ取得対象の S3 バケットにオブジェクトをコピーする

$ echo "Hello" > sample.txt
$ aws s3 cp sample.txt s3://source-bucket-test0123
upload: ./sample.txt to s3://source-bucket-test0123/sample.txt

ログ保存先の S3 バケットにログが保存されていることを確認

ログの反映まで時間がかかります。

$ aws s3 ls s3://logging-bucket-test0123/source-bucket-test0123/
2024-06-25 03:14:30        662 2024-06-25-03-14-29-3DB96FA6B22E3075
2024-06-25 03:16:33        677 2024-06-25-03-16-32-7CEEFCBEE900A67B
<中略>
2024-06-25 03:43:01        473 2024-06-25-03-43-00-92804174D9C7F97C
2024-06-25 03:43:33        728 2024-06-25-03-43-32-88F8DB138CA4BF1B

ログが出力されていることが確認できました。

ログの内容を確認してみる

本当は Athena でやるべきですが、ChatGPT に特定のプレフィックス内のオブジェクトの中身をすべて取得してひとつのファイルにまとめるサンプルを作ってもらい、正確に実行できるように加工しました。

#!/bin/bash

# バケット名とプレフィックスを設定
BUCKET_NAME="logging-bucket-test0123"
PREFIX="source-bucket-test0123"
OUTPUT_FILE="combined_output.txt"

# 一時ファイルを保管するディレクトリ
TEMP_DIR=$(mktemp -d)

# S3から特定のプレフィックス内のオブジェクト一覧を取得してダウンロード
aws s3api list-objects --bucket "$BUCKET_NAME" --prefix "$PREFIX" --query "Contents[].[Key]" --output text | while read -r KEY; do
  # ダウンロードされたオブジェクトのファイル名を決定
  FILE_NAME=$(basename "$KEY")
  # S3からオブジェクトをダウンロード
  aws s3 cp "s3://$BUCKET_NAME/$PREFIX/$FILE_NAME" "$TEMP_DIR/$FILE_NAME"
done

# ダウンロードしたファイルを一つのファイルに結合
cat $TEMP_DIR/* > "$OUTPUT_FILE"

# 一時ファイルをクリーンアップ
rm -rf "$TEMP_DIR"

echo "完成!結合されたファイルはここにあります:$OUTPUT_FILE"

内容を確認し、sample.txt をバケット内に保存したことを示すログが確認できました。

MASKED source-bucket-test0123 [25/Jun/2024:02:40:06 +0000] <IPAddress> arn:aws:sts::<AccountID>:assumed-role/<IAMRole>/<SessionName> 91J7WDK3KQSAMPLE REST.PUT.OBJECT sample.txt "PUT /sample.txt HTTP/1.1" 200 - - 6 40 20 "-" "aws-cli/2.16.11 md/awscrt#0.20.11 ua/2.0 os/linux#6.1.92-99.174.amzn2023.x86_64 md/arch#x86_64 lang/python#3.11.8 md/pyimpl#CPython exec-env/CloudShell cfg/retry-mode#standard md/installer#exe md/distrib#amzn.2023 md/prompt#off md/command#s3.cp" - MASKED SigV4 TLS_AES_128_GCM_SHA256 AuthHeader source-bucket-test0123.s3.ap-northeast-1.amazonaws.com TLSv1.3 - -

次回予告

ファイルの中身をすべて取得して目視で確認するのは大変なため、Athena でクエリをする方法を記事にします。

参考資料

Amazon S3 サーバーアクセスログを有効にします。 - Amazon Simple Storage Service