AWS LambdaとSESを使ったS3ファイルダウンロード通知の仕組み
背景
とある日
お客さん「業務システムからS3にファイルPUTされてるんやけど、権限ないからダウンロードしてファイルちょうだい」
ぼく「はい、このパスに配置しておきました。」
翌日
お客さん「また業務システムからS3にファイルPUTされてるから、ダウンロードしてファイルちょうだい」
ぼく「はい、このパスに配置しておきました。」
翌々日
お客さん「また業務システムからS3にファイルPUTされてるから、ダウンロードしてファイルちょうだい」
ぼく「はい、このパスに配置しておきました。」
~~以下無限ループ~~
めんどくさいんじゃ!!!!!!!!!!!!
ということで作りました。 いやほんとはたいした手間じゃないんですけどね。
構成
導入前
今2016年だよな、、、??と思うほどトラディショナルな仕組みでやってました。
導入前
いいですね、2016年はこうあるべきだと思います。
ただちょっと難点だったのは、SESが東京リージョンにリリースされていないこと。
たいした重要度でもないからまあいいや的な感じでエイッって作りましたが、
もっといいやり方があるんじゃないかと思ったり思わなかったり。
やったこと
SESの準備
email verification
- SES開く
- Identity ManagementのEmailAddressesクリック
- Verify a new email addressボタンをクリック
- 検証対象のメアド入力
- 指定したメアドにメールが届くので、メール内のリンクをクリック
- ブラウザ上のステータスがverifiedになっていることを確認
大前提として、fromに指定するemail addressを所有していることを確認するために、
上記の作業を実施する必要があります。
また、SESは、特に設定を施していない場合、sandboxという検証環境にあります。
その場合、toに指定するアドレスについても、verificationする必要があります。
本番サービスで稼働する場合は、sandboxの外に出す申請をすると思うのですが、
今回は内部的な処理なので、from,toどちらのアドレスともverificationを行っています。
lambdaの準備
Lambdaでやりたい処理は下記のとおりです。
- S3からのイベントを受け付けてBucketとKeyに分割
- boto3を使ってPresigned-URLを生成
- 生成したPresigned-URLを本文にメール送信
実装するとこうなります。
#!/usr/local/bin/python from __future__ import print_function import boto3 import os import sys ADMIN_EMAIL = 'xxxxxx@gmail.com' s3_client = boto3.client('s3') ses_client = boto3.client('ses', region_name='us-west-2') def send_email(to, reply, subject, body): response = ses_client.send_email( Source=ADMIN_EMAIL, Destination={ 'ToAddresses': [ to, ] }, Message={ 'Subject': { 'Data': subject, }, 'Body': { 'Text': { 'Data': 'Please download the file from this url.\n'+body, }, } }, ReplyToAddresses=[ reply, ], ReturnPath=ADMIN_EMAIL ) def send_mail_from_admin(to, message): send_email(to, ADMIN_EMAIL, "S3 notification", message) def lambda_handler(event, context) : for record in event['Records']: bucket = record['s3']['bucket']['name'] key = record['s3']['object']['key'] print(bucket) print(key) generated_url=(s3_client.generate_presigned_url( ClientMethod = 'get_object', Params = {'Bucket' : bucket, 'Key' : key}, ExpiresIn = 3600, HttpMethod = 'GET')) send_mail_from_admin('xxxxxx@gmail.com', generated_url)
boto3があればなんでも簡単に書けちゃいますね。
コメントとかないのはご容赦ください。
なお、lambda実行時にlambda_functionが呼び出されるよう、設定しています。
lambdaの権限設定として、ロールに下記のポリシーをアタッチ
- S3触る
- SES触る
S3のイベント通知設定
配置対象のbucketのプロパティで、
特定のフォルダに特定の拡張子のファイルが配置された際に、
lambdaを呼び出すよう設定しています。
まとめ
lambdaを使って簡単な仕組みを構築してみました。
こういったお遊びシステムだとあまり気になりませんが、
本番導入時には、下記のような観点が気になるかなと思いました。
上司からは無停止デプロイや、エラー時の問題切り分けが難しそうだよねというご指摘をいただきました。
たしかに。
エンタープライズレベルのシステムで適用できるように、いろいろ考えたいと思います。
それでは。