問題
以下のようなコードコードを実行し
letprev=null;try{prev=awaitS3.getObject({Bucket:'my-bucket-hogehoge',Key:'path/to/object',}).promise();}catch(e){// オブジェクトが存在しない場合(NoSuchKey)は無視,それ以外は throw し直すif(e.code!=='NoSuchKey'){throwe;}}
存在しないオブジェクトへのアクセスは NoSuchKey
が返ってくるものと期待していて、s3rverを利用したローカル環境での動作確認はそれで問題なかった。
しかし、デプロイして実際にどうさせると AccessDenied が返ってくる。
原因
なんで?
と1時間くらい悩んだが SDK のドキュメントに書いてあった
https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#getObject-property
Permissions
You need the s3:GetObject permission for this operation. For more information, see Specifying Permissions in a Policy. If the object you request does not exist, the error Amazon S3 returns depends on whether you also have the s3:ListBucket permission.
- If you have the s3:ListBucket permission on the bucket, Amazon S3 will return an HTTP status code 404 ("no such key") error.
- If you don’t have the s3:ListBucket permission, Amazon S3 will return an HTTP status code 403 ("access denied") error.
s3:ListBucket
Action が許可されていないと access denied
を返すと
対応
以下のようにポリシードキュメントで権限を付与したら解決。
Resource の指定方法が s3:getObject
と異なるので注意。
(一部抜粋){"Action":["s3:GetObject","s3:PutObject"],"Resource":"arn:aws:s3:::my-bucket-hogehoge/*","Effect":"Allow"},{"Action":["s3:ListBucket"],"Resource":"arn:aws:s3:::my-bucket-hogehoge","Effect":"Allow"}