問題
以下のようなコードコードを実行し
let prev = null;
try {
prev = await S3.getObject({
Bucket: 'my-bucket-hogehoge',
Key: 'path/to/object',
}).promise();
} catch(e) {
// オブジェクトが存在しない場合(NoSuchKey)は無視,それ以外は throw し直す
if (e.code !== 'NoSuchKey') {
throw e;
}
}
存在しないオブジェクトへのアクセスは 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
を返すと
追記: 2021-04-01
API リファレンスのほうにも記載があったのでリンクを貼っておく
対応
以下のようにポリシードキュメントで権限を付与したら解決。
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"
}