はじめに
LaravelでAmazon S3へ画像アップロードする処理を実装し、いざアップロードしようとしたところ、以下のエラーが出て失敗しました。
Error executing "PutObject" on "https://minna-no-houteishiki.s3.ap-northeast-1.amazonaws.com/r1oJ01mYWVeol0m7jUTji7uef5lyG7MATNOqzl1A.png"; AWS HTTP error: Client error: `PUT https://minna-no-houteishiki.s3.ap-northeast-1.amazonaws.com/r1oJ01mYWVeol0m7jUTji7uef5lyG7MATNOqzl1A.png` resulted in a `403 Forbidden` response:
<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>AccessDenied</Code><Message>Access Denied</Message><RequestId>ABBC2D (truncated...)
AccessDenied (client): Access Denied - <?xml version="1.0" encoding="UTF-8"?>
<Error><Code>AccessDenied</Code><Message>Access Denied</Message><RequestId>ABBC2D1C8E07A319</RequestId><HostId>ZvHZ5rneZGsSstZLX2jIoixQFaaFnRxFdtoiNE1Hd+0n17a09y4JKDckdlYsZOC/nMhiQuBb3fA=</HostId></Error>
PutObject
というコマンドを実行したところ、アクセスが拒否されてしまったようです。
原因
S3のバケットにパブリックアクセス設定機能が設定されているためです。パブリックアクセス設定機能とは、バケット内のファイルをパブリックアクセスできないようにする設定のことです。
Amazon S3のセキュリティについては、以下の記事が大変よくまとまっているため参照してください。
S3で誤ったデータの公開を防ぐパブリックアクセス設定機能が追加されました | Developers.IO
つまり、Amazon S3にパブリックアクセス設定機能が追加されたことにより、デフォルトでパブリックアクセスができなくなったということです。
ちなみに、Laravelの実装は以下のようになっています。
$image = $request->file('image');
$path = Storage::disk('s3')->put('/', $image, 'public');
$post->image = Storage::disk('s3')->url($path);
put
メソッドの第3引数にpublic
を指定しており、ファイルをパブリックファイルとしてアップロードしようとしています。public
を指定せずにアップロードしても、アップロードはできても参照ができないため、意味がありません。
対処方法
AWS管理コンソールにサインインし、Amazon S3のバケット管理画面にアクセスします。
パブリックアクセス設定機能を以下のように変更します。
- パブリックアクセスをすべてブロック:オフ
- 新しいアクセスコントロールリスト (ACL) を介して許可されたバケットとオブジェクトへのパブリックアクセスをブロックする:オフ
- 任意のアクセスコントロールリスト (ACL) を介して許可されたバケットとオブジェクトへのパブリックアクセスをブロックする:オフ
- 新規のパブリックバケットポリシーまたはアクセスポイントポリシーを介して付与されたバケットとオブジェクトへのパブリックアクセスをブロックする:オン
- 任意のパブリックバケットポリシーまたはアクセスポイントポリシーを介したバケットとオブジェクトへのパブリックアクセスとクロスアカウントアクセスをブロックする:オン
正直、日本語がわかりにくいのでどれをオフにしたらいいかよくわかりません…😅
パブリックアクセス設定機能はセキュリティを高める設定のため、オフにするのは最小限にとどめたほうがいいです。
私の場合は上記のような設定でアップロードできるようになりました。
まとめ
LaravelでAmazon S3へアップロードする方法を解説している記事はたくさんありますが、いずれもAWSのセキュリティ設定が変更される前の記事のため、手順通り設定しているのにアップロードできないという事態に陥ることが多いと思います。
Amazon S3へのアップロードができないという人は参考にしていただければと思います。