2021/3/18 にS3 のGet 時にLambda を実行できる新機能がリリースされました。
S3 Object Lambda で、S3 GET リクエストに独自のコードを追加して、データがアプリケーションに返されるときにデータを変更および処理することが可能に
この機能を利用することで、S3 へのGET オペレーション時に独自のコードを実行し、オブジェクトに対する処理を実行して、処理したオブジェクトをクライアントに返すことができます。
利用方法に関しては、以下のAWS News Blog 記事を参考にできます。
Introducing Amazon S3 Object Lambda – Use Your Code to Process Data as It Is Being Retrieved from S3
ここでは、上記ブログ記事の内容を実際に試してS3 Object Lambda を動かしてみたいと思います。
手順概要
- Lambda 関数を作成する
- コードの実行に必要なライブラリをLambda Layer で設定する
- Lambda 用のIAM ロールにポリシーを追加
- S3 バケットを作成し、アクセスポイントを作成する
- オブジェクトLambda アクセスポイントを作成する
- 動作確認をする
では順を追って実施していきましょう。
Lambda 関数を作成する
今回は全般的にマネージメントコンソール上で操作していきます。まずは、マネージメントコンソールにログインしてください。今回は、Lambda 関数をバージニア北部リージョンに作成します。
バージニア北部リージョンで、AWS Lambda サービスにアクセスしてください。関数の作成から、以下のようにPython 3.8 を選択して関数を作成してください。アクセス権限はデフォルトで作成しますが、後でS3 Object Lambda を動かすためにIAM ロールに必要な権限を追加します。

Lambda には以下のコードを記述してください。
import boto3 import requests def lambda_handler(event, context): print(event) object_get_context = event["getObjectContext"] request_route = object_get_context["outputRoute"] request_token = object_get_context["outputToken"] s3_url = object_get_context["inputS3Url"] # Get object from S3 response = requests.get(s3_url) original_object = response.content.decode('utf-8') # Transform object transformed_object = original_object.upper() # Write object back to S3 Object Lambda s3 = boto3.client('s3') s3.write_get_object_response( Body=transformed_object, RequestRoute=request_route, RequestToken=request_token) return {'status_code': 200}
Lambda 関数の作成は以上です。
コードの実行に必要なライブラリをLambda Layer で設定する
先程のコードを実行するためには、requests ライブラリが必要です。また現時点でLambda 環境に組み込まれているPython 用のSDK(boto3) のバージョンが古く、S3 Object Lambda を利用できません。そこで、Python のrequests ライブラリとboto3 の最新バージョンを利用できるようにする必要があります。
今回はテスト目的なので、こちらの方が用意してくれているLambda Layer を設定します。ちょっとPython でLambda 機能を試してみたい時に、Layer で必要なライブラリを組み込めるので非常に便利で助かります!
Lambda Layer の設定の仕方は、上記のGithub の手順を参照してください。
Github に記載されている以下のLink からリージョンごとのパッケージの一覧を参照します。

今回はバージニア北部(us-east-1) なので、そのcsv ファイルをクリックします。

requests の最新版を探してarn の内容を控え、Lambda Layer を登録してください。

boto3 の最新版を探してarn の内容を控え、Lambda Layer を登録してください。S3 Object Lambda API の内容は、1.17.31 から含まれているようなので、それ以上のバージョンであればS3 Object Lambda に対応しています。

Lambda 用のIAM ロールにポリシーを追加
Lambda コード内で、”WriteGetObjectResponse” API の呼び出しを行っていますので、この権限をLambda 用のIAM ロールに追加する必要があります。
マネージメントコンソールにて、Lambda 関数の、”設定” タブ -> アクセス権限 を選択し、ロール名のリンクをクリックします。

アクセス権限にて、インラインポリシーの追加 をクリックします。

以下のJSON の内容で、インラインポリシーを作成してください。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowObjectLambdaAccess",
"Action": [
"s3-object-lambda:WriteGetObjectResponse"
],
"Effect": "Allow",
"Resource": "*"
}
]
}
IAM ロールの設定は以上です。
S3 バケットを作成し、アクセスポイントを作成する
マネージメントコンソールで、バージニア北部に適当なS3 バケットをデフォルト設定で作成してください。
作成したバケットにアクセスポイントを作成してください。アクセスポイント名を指定して、ネットワークオリジンを”インターネット” にして、後はデフォルトのまま作成してください。

オブジェクトLambda アクセスポイントを作成する
S3 マネージメントコンソールのナビゲーションペインに「オブジェクト Lambda アクセスポイント」というメニューが増えていますので、こちらをクリックし、「オブジェクト Lambda アクセスポイントの作成」ボタンをクリックします。

“オブジェクト Lambda アクセスポイント名” に適当に名前を入れ、先程作成したアクセスポイントを選択します。

“Lambda 関数の呼び出し” にて、先ほど作成したLambda を選択します。

“ペイロード – オプション” に記述をしておくと、Lambda 実行時のイベント引数でペイロードも渡ってきます。

残りはデフォルトのままで、”オブジェクト Lambda アクセスポイントの作成” ボタンを押します。
動作確認をする
以上で、設定は完了です。動作確認をしてみましょう。
まずは、S3 バケットにファイルをアップロードします。今回Lambda に設定したPython コードは、テキストをすべて大文字に変換するという内容になっていますので、小文字のテキストを記述したファイルを用意してアップロードしてください。例えば以下のような内容のファイルを作成してS3 バケットにアップロードしてください。
amazon s3 object lambda test
マネージメントコンソールでの確認
“オブジェクト Lambda アクセスポイント” から先程作成したオブジェクト Lambda アクセスポイントを選択します。

バケットにアップロードしたファイルが表示されますので、チェックを入れてアクションから”ダウンロード” を選択します。

ブラウザ上に、全て大文字に変換された内容が表示されれば正常に動作しています。
AMAZON S3 OBJECT LAMBDA TEST
Lambda の実行時のログをCloudWatch で確認してみてください。
AWS CLI での確認
以下のようにコマンドを実行すると確認できます。なお、cli は最新バージョンにアップデートしておいてください。(2.1.31 以上)
オリジナルのオブジェクトを取得する場合は、以下のようにバケット名を入れてください。
aws s3api get-object --bucket <your_bucket_name> --key <your_object_key> obj-org.txt
S3 Object Lambda 経由でオブジェクトを取得する場合は、以下のようにオブジェクト Lambda アクセスポイントのARN を”–bucket” に指定してください。
aws s3api get-object --bucket arn:aws:s3-object-lambda:us-east-1:<youraccount>:accesspoint/<your_object_lambda_ap> --key <your-object-key> obj-lambda.txt
トラブルシューティング
Lambda の実行に失敗すると以下のような表示になります。

エラーが発生した場合は、Lambda の実行時のログをCloudWatch Logs でチェックしてください。例えば、以下のような内容が表示されている場合は、Lambda に必要な権限がないということになりますので、IAM ロールに指定したポリシーを見直してみてください。

以上となります。最後までご参照いただきましてありがとうございました。