S3サーバーアクセスログにソースリージョン情報が追加 — クロスリージョンアクセスの可視化が一気に楽になりました
S3のサーバーアクセスログにSource Regionフィールドが新たに追加されました(2026年2月23日 AWS What’s New)。リクエストがどのAWSリージョンから来たのかが、ログを見るだけでわかるようになります。
これまでクロスリージョンのアクセスパターンを把握するには、Remote IPフィールドからAWSのIP範囲と突合するか、VPC Flow Logsを併用する必要がありました。それが1つのフィールドで済むようになったのは、地味ですがセキュリティ運用の現場にとってはかなり助かるアップデートだと思います。
何が変わったのか
公式ドキュメントにはログフォーマットについて以下のように記載されています(AWS Documentation)。
Source Regionフィールドは、サーバーアクセスログの27番目のフィールド(最後尾)として追加されています。設定変更は不要で、サーバーアクセスログを有効にしているバケットに自動的に反映されます。
たとえば、us-west-2のアプリケーションがap-northeast-1にあるバケットにリクエストを送った場合、ログの最後にus-west-2と記録されます。
ログフォーマットの全体像
S3サーバーアクセスログは全27フィールドのスペース区切りです。今回追加されたSource Regionは末尾に位置します。
主要なフィールドとSource Regionの関係を整理しておきます。
| # | フィールド | 内容 | Source Regionとの関係 |
|---|---|---|---|
| 4 | Remote IP | リクエスト元のIPアドレス | Source RegionはこのIPをリージョンに解決したもの |
| 23 | Host Header | 接続先のS3エンドポイント | バケットのリージョン(宛先)を示す |
| 25 | Access Point ARN | アクセスポイントのARN | アクセスポイントのリージョンを含む |
| 27 | Source Region | リクエスト元のAWSリージョン | 今回追加された新フィールド |
つまり、Host Header(フィールド23)でバケットの所在リージョンがわかり、Source Region(フィールド27)でリクエスト元のリージョンがわかるので、この2つを見るだけでクロスリージョンアクセスかどうかが即座に判定できます。
Source Regionが-になるケース
見落としがちですが、Source Regionフィールドが常にリージョン名を返すわけではありません。公式ドキュメントによると、以下のケースでは-(ダッシュ)が記録されます。
- PrivateLink経由の接続
- Direct Connect経由の接続
- BYOIP(Bring Your Own IP)アドレスからの接続
- AWS外のIPアドレス(オンプレミスや他クラウド)からの接続
- S3内部ポリシーによるオペレーション(ライフサイクル遷移、チェックサム計算など)
ここは注意が必要です。つまり、オンプレミスからのアクセスや、PrivateLinkを通じたアクセスではSource Regionが取得できません。社内ネットワークからS3にアクセスしているケースが多い環境では、このフィールドだけに頼ることはできない点を認識しておく必要があります。
逆に言えば、Source Regionが記録されるのはAWSのリージョン内リソースからのアクセスに限られるため、このフィールドが埋まっていること自体が「AWSリソースからのアクセスである」という情報を暗黙的に持っています。
セキュリティ運用での活用
自分がこの機能を見てまず思い浮かべたのは、以下のようなユースケースです。
想定外のリージョンからのアクセス検知
本来ap-northeast-1からしかアクセスされないはずのバケットに、us-east-1やeu-west-1からリクエストが来ていたら、それは調査対象です。これまではRemote IPをAWSのIP範囲JSONと突合して判定する必要がありましたが、Source Regionフィールドを見るだけで済むようになりました。
Athenaでクエリを書くなら、以下のようなイメージです。
SELECT
request_time,
remote_ip,
operation,
key,
source_region
FROM s3_access_logs
WHERE bucket = 'my-important-bucket'
AND source_region != '-'
AND source_region != 'ap-northeast-1'
ORDER BY request_time DESC
LIMIT 100;
クロスリージョン転送コストの可視化
S3のクロスリージョンデータ転送には料金がかかります。Source Regionフィールドを使えば、どのリージョンからどれだけのデータが読まれているかを集計できます。
SELECT
source_region,
COUNT(*) AS request_count,
SUM(bytes_sent) AS total_bytes
FROM s3_access_logs
WHERE source_region != '-'
AND source_region != 'ap-northeast-1'
GROUP BY source_region
ORDER BY total_bytes DESC;
不要なクロスリージョンアクセスが見つかれば、S3レプリケーションやMulti-Region Access Pointの導入を検討するきっかけになります。
CloudTrailとの使い分け
S3のアクセス記録には大きく2つの選択肢があります。
| サーバーアクセスログ | CloudTrailデータイベント | |
|---|---|---|
| Source Region | あり(新フィールド) | なし(awsRegionはバケット側のリージョン) |
| 認証失敗の記録 | あり | なし |
| 料金 | 無料(ストレージ代のみ) | イベントごとに課金 |
| フォーマット | スペース区切り | JSON |
| 配信遅延 | 数分〜数時間 | ほぼリアルタイム |
CloudTrailのawsRegionフィールドはあくまでバケットが存在するリージョン(宛先)を示すものであり、リクエスト元のリージョンではありません。つまり、クロスリージョンアクセスの「元」を知りたい場合は、現時点ではサーバーアクセスログのSource Regionフィールドが唯一の直接的な手段です。
実際に試してみた
自分の環境でサーバーアクセスログを有効化して、Source Regionフィールドが実際にどう記録されるか確認してみました。
- AWS CLI:
aws-cli/2.34.3 - リージョン:
ap-northeast-1
バケットの準備
テスト用にバケットを2つ作成し(ソースバケットとログ出力先バケット)、サーバーアクセスログを有効化します。
# ログ出力先バケットを作成
aws s3api create-bucket \
--profile your-profile \
--bucket my-log-test-bucket-logs \
--region ap-northeast-1 \
--create-bucket-configuration LocationConstraint=ap-northeast-1
# ソースバケットを作成
aws s3api create-bucket \
--profile your-profile \
--bucket my-log-test-bucket \
--region ap-northeast-1 \
--create-bucket-configuration LocationConstraint=ap-northeast-1
ここで1つ注意点があります。2023年4月以降に作成されたバケットはデフォルトでACLが無効(BucketOwnerEnforced)になっています。この場合、ログ出力先バケットにバケットポリシーでlogging.s3.amazonaws.comへの書き込み権限を付与する必要があります。
aws s3api put-bucket-policy \
--profile your-profile \
--bucket my-log-test-bucket-logs \
--policy '{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "S3ServerAccessLogsPolicy",
"Effect": "Allow",
"Principal": {
"Service": "logging.s3.amazonaws.com"
},
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::my-log-test-bucket-logs/logs/*",
"Condition": {
"StringEquals": {
"aws:SourceAccount": "123456789012"
}
}
}
]
}'
自分は最初このポリシーを設定し忘れて、30分以上ログが配信されず首を傾げていました。サーバーアクセスログは配信エラーが通知されないため、権限不足に気づきにくい点は注意が必要です。
バケットポリシーを設定したら、サーバーアクセスログを有効化します。
aws s3api put-bucket-logging \
--profile your-profile \
--bucket my-log-test-bucket \
--bucket-logging-status '{
"LoggingEnabled": {
"TargetBucket": "my-log-test-bucket-logs",
"TargetPrefix": "logs/"
}
}'
リクエストの発生
テストオブジェクトをアップロードして、ローカル環境からいくつかリクエストを発生させます。
echo "hello" | aws s3 cp - s3://my-log-test-bucket/test-object.txt --profile your-profile
aws s3api head-object --profile your-profile --bucket my-log-test-bucket --key test-object.txt
aws s3api get-object --profile your-profile --bucket my-log-test-bucket --key test-object.txt /dev/null
さらに、Source Regionの違いを確認するために、ap-northeast-1とus-east-1にそれぞれLambda関数を作成し、AWSリソースからのアクセスも発生させました。
ログの確認
S3サーバーアクセスログはベストエフォートで配信されるため、数十分〜数時間かかります。自分の環境では、バケットポリシーを正しく設定してから約30分後に最初のログが配信されました。
aws s3 ls s3://my-log-test-bucket-logs/logs/ --profile your-profile
ローカル環境からのアクセスログ
ローカル環境(AWS外)からのリクエストのログを確認すると、末尾のSource Regionフィールドは-になっていました。
... SigV4 TLS_AES_128_GCM_SHA256 AuthHeader my-log-test-bucket.s3.ap-northeast-1.amazonaws.com TLSv1.3 - - -
最後の3つのフィールドは、Access Point ARN(-)、ACL Required(-)、Source Region(-) です。AWS外のIPアドレスからのアクセスなので、Source Regionが特定できず-になるのは前述のとおり想定どおりです。
Lambda(ap-northeast-1)からのアクセスログ
ap-northeast-1のLambdaからのアクセスでは、末尾に**ap-northeast-1**が記録されました。
... SigV4 TLS_AES_128_GCM_SHA256 AuthHeader my-log-test-bucket.s3.ap-northeast-1.amazonaws.com TLSv1.3 - - ap-northeast-1
バケットと同じリージョンからのアクセスなので、これは同一リージョンアクセスです。
Lambda(us-east-1)からのアクセスログ
us-east-1のLambdaからのアクセスでは、末尾に**us-east-1**が記録されました。
... SigV4 TLS_AES_128_GCM_SHA256 AuthHeader my-log-test-bucket.s3.ap-northeast-1.amazonaws.com TLSv1.3 - - us-east-1
バケットはap-northeast-1にあるのにリクエスト元がus-east-1なので、これがクロスリージョンアクセスです。Host Headerのap-northeast-1(宛先)とSource Regionのus-east-1(元)を比較するだけで、クロスリージョンアクセスであることが一目でわかります。
検証結果のまとめ
| リクエスト元 | Remote IP | Source Region |
|---|---|---|
| ローカル環境(AWS外) | グローバルIP | - |
| Lambda(ap-northeast-1) | AWS内部IP | ap-northeast-1 |
| Lambda(us-east-1) | AWS内部IP | us-east-1 |
AWSリソースからのアクセスにはリージョン名が記録され、AWS外からのアクセスには-が記録されることが確認できました。
ログパーサーの更新が必要
既存のログパーサーを使っている場合は注意が必要です。フィールドが26個から27個に増えたため、固定のフィールド数を前提としたパーサーではエラーが出る可能性があります。
公式ドキュメントには以下の記載があります(AWS Documentation)。
Amazon S3 may add new fields to the end of log records. Ensure your parsing code can handle trailing fields it doesn’t recognize.
AWSも以前から「末尾にフィールドが追加される可能性がある」と注意喚起していたわけですが、今回がまさにそのケースです。Athenaのテーブル定義やGlueのクローラ設定、カスタムのログパーサーを使っている場合は、27番目のフィールドを追加する更新が必要です。
料金
このアップデートに追加料金はかかりません。サーバーアクセスログの利用自体が無料で(ログファイルのストレージ料金のみ)、Source Regionフィールドも同様に無料で利用できます(2026年2月23日 AWS What’s New)。
まとめ
S3サーバーアクセスログへのSource Regionフィールド追加は、地味ながら実用性の高いアップデートです。
自分が特に評価しているのは以下の点です。
- 設定不要: サーバーアクセスログが有効であれば自動的に記録される
- クロスリージョンアクセスの直接判定: Host Header(宛先)とSource Region(元)の組み合わせで即座に判定可能
- コスト分析への活用: クロスリージョン転送の発生元を特定しやすくなる
一方で、PrivateLink・Direct Connect・オンプレミスからのアクセスでは-になる点は意識しておく必要があります。これらの経路からのアクセスも監視したい場合は、CloudTrailやVPC Flow Logsとの併用が引き続き必要です。
既存のログパーサーを運用している方は、27番目のフィールド対応を忘れずに更新してください。