S3レプリケーション完了をトリガーにLambdaでファイルを日付リネームする自動化
はじめに
こんにちは、クラウド事業部の松岡です。 インフラエンジニア3年目、AWS経験3か月の私が、S3のレプリケーション機能とEventBridge + Lambdaを組み合わせて、同期されたファイルを自動で整理(日付リネーム)する仕組みを構築しました。
「AWSの複数リソースを組み合わせて触ってみたい」という初級〜中級者の方に向けて、実務で意識すべき最小権限の原則を含めた手順を紹介します。
システム構成図
本構成では、S3間のレプリケーションが完了したことをEventBridgeで検知し、即座にLambdaがファイル名を変更して特定のディレクトリへ整理する仕組みを採用しています。

処理の流れ
- アップロード: ユーザーが
filetransfer-dev-source-bucketへファイルを配置。 - 同期: S3のレプリケーション機能により
filetransfer-dev-destination-bucketへ自動コピー。 - 検知: EventBridgeが送信先バケットへの配置(Object Created)をリアルタイムで検知。
- リネーム: Lambdaが起動。配置時間をファイル名に付与し、
processed/ディレクトリへ移動。
構築リソース一覧
リソース名は {systemname}-{Env}-{Resourcename} の規則に従い、管理を容易にしています。
下記にYAMLファイルを配置しているので必要でしたらご利用ください
https://github.com/tmatusoka-apc/s3-filetransfer.git
| カテゴリ | リソース名 | 備考 |
|---|---|---|
| S3 (Source) | filetransfer-dev-source-bucket |
バージョニング有効 / レプリケーション元 |
| S3 (Dest) | filetransfer-dev-destination-bucket |
バージョニング有効 / EventBridge通知有効 |
| EventBridge | filetransfer-dev-s3-put-rule |
Object Created イベントを監視 |
| Lambda | filetransfer-dev-rename-function |
Python 3.12 / 無限ループ防止実装済み |
| IAM Role | filetransfer-dev-replication-role |
S3間のコピー権限(最小権限) |
| IAM Role | filetransfer-dev-lambda-role |
送信先S3の操作とログ出力権限 |
1. S3レプリケーションの設定
S3間のデータ同期を安全に行うための設定です。
設定のポイント
- バージョニング: レプリケーションの必須要件のため、両バケットで有効化します。
- 最小権限のIAMロール:
s3.amazonaws.comを信頼ポリシーに設定。- 許可ポリシーでは、Sourceからの
GetObjectと DestinationへのReplicateObjectに限定して記述します。
2. Lambdaによるファイル転送の実装
EventBridgeから起動されるLambdaを構築します。
権限周りの設計
本番環境を意識し、以下の権限を持つIAMロールを作成します。
* S3: GetObject, PutObject, DeleteObject(送信先バケットのみ)。
* CloudWatch Logs: 実行ログ(/aws/lambda/filetransfer-dev-rename-function)の書き込み権限。
Lambdaコード(抜粋)
S3には「リネーム」コマンドが存在しないため、「コピー + 削除」の手順を踏みます。
import boto3 import os from datetime import datetime s3 = boto3.client('s3') def lambda_handler(event, context): bucket = event['detail']['bucket']['name'] old_key = event['detail']['object']['key'] # 無限ループ防止: 既に処理済みディレクトリにある場合はスキップ if old_key.startswith('processed/'): return # 配置された時間を取得(YYYYMMDD-HHMMSS形式) timestamp = datetime.now().strftime('%Y%m%d-%H%M%S') new_key = f"processed/{timestamp}_{os.path.basename(old_key)}" print(f"Moving: {old_key} -> {new_key}") # 同一バケット内でのコピー&元のオブジェクト削除 s3.copy_object( Bucket=bucket, CopySource={'Bucket': bucket, 'Key': old_key}, Key=new_key ) s3.delete_object(Bucket=bucket, Key=old_key) return {"status": "success"}
3. 実行確認
- Sourceへアップロード:
test.pngをアップロード。 - レプリケーション確認: Destinationへ
test.pngが届くのを確認。 - CloudWatch Logsを確認: Lambdaが正常に起動し、
Moving...のログが出ているかチェック。 - 最終結果: Destinationの
processed/配下に20260129-120000_test.pngが生成され、元のファイルが消えていれば成功。
おわりに
インフラエンジニアとして、単に「動く」だけでなく、「権限が適切か」「後で削除や変更がしやすい命名規則になっているか」を意識した構築を心がけました。
今後は、エラー発生時にSNSで通知する仕組みや、Step Functionsを用いたより複雑なワークフローにも挑戦してみたいと思います。