Lambda が S3 で AccessDenied になるときの確認ポイント ── 実行ロールにポリシーを付ける
記事の「実践」を 1 項目ずつ進めるためのページです。AWS マネジメントコンソールで操作したら、右の一覧にチェックを入れてください。チェックはこのブラウザに保存されます。
前提条件
- リージョン:
ap-northeast-1(東京) - 以下のリソースが作成済みであること
まだ用意していない場合は、「作り方の参考」の記事の手順で作れます。リソース名は、この記事の名前に読み替えてください。
| リソース種別 | リソース名 | 内容 | 作り方の参考 |
|---|---|---|---|
| S3 バケット(転送元) | dva-convert-src-<アカウントID> | 変換前のテキストファイルを置く | Amazon S3 でバケットを作成しオブジェクトを管理する |
| S3 バケット(出力先) | dva-convert-dst-<アカウントID> | 変換後のファイルを置く | 同上 |
| IAM ポリシー(カスタマー管理) | dva-convert-s3-policy | 転送元の s3:GetObject、出力先の s3:PutObject、CloudWatch Logs への出力を許可 | AWS IAM でユーザー・ロール・ポリシーを作成しアクセス制御する |
作成するリソース一覧
| リソース種別 | リソース名 | 用途 |
|---|---|---|
| Lambda 関数 | dva-convert-fn | テキストファイルを変換して出力先に書く |
| IAM ロール | dva-convert-fn-role-xxxxxxxx(自動作成) | 関数の実行ロール |
| S3 トリガー | (転送元バケット・サフィックス .txt) | ファイルの配置で関数を呼ぶ |
手順 1: 関数を作る
AWS マネジメントコンソールにログインし、リージョンが ap-northeast-1(東京)であることを確認します。上部の検索バーに Lambda と入力し、「Lambda」を選択します。
「関数を作成」をクリックし、以下を設定します。
- 「一から作成」を選択
- 関数名:
dva-convert-fn - ランタイム:
Python 3.13 - 実行ロール: 「その他の設定」の「カスタム実行ロール」はオフ(デフォルト)のまま。CloudWatch Logs への出力だけを許可する実行ロールが自動で作られます
画面下部の「関数を作成」をクリックします(作成後に案内のダイアログが出たら閉じます)。「コード」タブのエディタで lambda_function.py を次の内容に置き換え、「Deploy」をクリックします。DST_BUCKET の <アカウントID> は自分のアカウント ID に置き換えます。
import urllib.parse
import boto3
s3 = boto3.client("s3")
DST_BUCKET = "dva-convert-dst-<アカウントID>"
def lambda_handler(event, context):
for record in event["Records"]:
src_bucket = record["s3"]["bucket"]["name"]
key = urllib.parse.unquote_plus(record["s3"]["object"]["key"])
body = s3.get_object(Bucket=src_bucket, Key=key)["Body"].read().decode("utf-8")
converted = body.upper() # 変換処理の代わりに大文字にする
out_key = key.rsplit(".", 1)[0] + ".converted.txt"
s3.put_object(Bucket=DST_BUCKET, Key=out_key, Body=converted.encode("utf-8"))
print(f"converted s3://{src_bucket}/{key} -> s3://{DST_BUCKET}/{out_key}")
手順 2: S3 トリガーを追加する
関数の概要の「トリガーを追加」をクリックし、以下を設定します。
- ソース:
S3 - バケット:
dva-convert-src-<アカウントID>(一覧から選んで「入力が無効です」と表示される場合は、arn:aws:s3:::dva-convert-src-<アカウントID>と ARN で入力します) - イベントタイプ: 「すべてのオブジェクト作成イベント」
- サフィックス - オプション:
.txt - 「再帰呼び出し」の確認のチェックボックスにチェック(出力先は別のバケットなので、再帰にはなりません)
「追加」をクリックします。
手順 3: ファイルを置いて AccessDenied を確かめる
S3 のコンソールで dva-convert-src-<アカウントID> を開き、次の内容の hello.txt をアップロードします。
hello from the banana warehouse
Lambda のコンソールに戻り、dva-convert-fn の「モニタリング」タブ →「CloudWatch Logs を表示」をクリックして、最新のログストリームを開きます。An error occurred (AccessDenied) when calling the GetObject operation のエラーが記録されています。トリガーで関数は呼ばれたものの、関数が転送元バケットを読めなかったことが分かります。
手順 4: 実行ロールにポリシーをアタッチする
dva-convert-fn の「設定」タブ →「アクセス権限」を選択します。「実行ロール」に表示されているロール名(dva-convert-fn-role- で始まる名前)をクリックすると、IAM コンソールでロールが開きます。「許可ポリシー」には、CloudWatch Logs への出力だけを許可するポリシーが付いています。
「許可を追加」→「ポリシーをアタッチ」を選択します。検索欄に dva-convert-s3-policy と入力し、チェックを入れて「許可を追加」をクリックします。
手順 5: もう一度ファイルを置く
S3 のコンソールで、転送元バケットに hello.txt をもう一度アップロードします(同じ名前で上書きすると、新しい作成イベントとして関数が呼ばれます)。
出力先の dva-convert-dst-<アカウントID> を開くと、hello.converted.txt が作られています。オブジェクトを開いて「開く」をクリックすると、内容が HELLO FROM THE BANANA WAREHOUSE になっていることを確認できます。CloudWatch Logs にも converted s3://... -> s3://... のログが記録されます。