【AWS S3】バケット内オブジェクトが無い時は403?404?
作成日時: 2023/06/24
更新日時: 2023/06/24
# 概要
cloudfrontでエラー処理をする際に少し困ったのでメモ程度に書き残しておきます。
バケット内でオブジェクトが存在しないパスへアクセスした際の挙動についてです。
# 調査
[Amazon S3 からの HTTP 404 エラー「NoSuchKey」をトラブルシューティングする方法を教えてください。](https://repost.aws/ja/knowledge-center/404-error-nosuchkey-s3#:~:text=403%20Access%20Denied%20%E3%82%A8%E3%83%A9%E3%83%BC)
上記の記事を見ると、どうやらバケットポリシーに`GetObject`があっても **`ListBucket`の有無でエラーレスポンスが変わるらしい。**
あくまで推測ですが、`GetObject`した後にバケット自体があるか確認するため`ListBucket`してるんでしょうね(`GetObject`->オブジェクトがない->`ListBucket`->`ListBucket`権限がない->403エラー)。
実際バケット自体が無い場合は`NoSuchBucket`と、別のエラーが返ります。
# 動作確認
## GetObjectのみの場合
```json
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "1",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::test-haroot/*",
"Condition": {
"IpAddress": {
"aws:SourceIp": "###.###.###.##/32"
}
}
}
]
}
```
上記のような`test-haroot`バケット配下に`GetObject`権限のみ与えて存在しないバケットにアクセスしてみます。

Access Deniedが返ってきました。
ChromeでDevToolsも見ておきます。

ステータスコード403が返ってきてるのが確認できました。
## ListBucketを追加した場合
```json
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "1",
"Effect": "Allow",
"Principal": "*",
"Action": [
"s3:GetObject",
"s3:ListBucket" ←ここ
],
"Resource": [
"arn:aws:s3:::test-haroot/*",
"arn:aws:s3:::test-haroot" ←ここ
],
"Condition": {
"IpAddress": {
"aws:SourceIp": "###.###.###.##/32"
}
}
}
]
}
```
Actionに`s3:ListBucket`を追加します。
また`ListBucket`の対象はバケット自体なのでResourceにもバケット自体のリソース名(`arn:aws:s3:::${バケット名}`)を追加します。
アクセスして画面を確認します。

レスポンスが`NoSuchKey(The specified key does not exist.)`に変わりました。
DevToolsも見ます。

エラーコードも404に変わってます。
挙動的にはこちらの方が正しそうですね。
# 結論
バケットポリシーに`GetObject`を付ける場合は`ListBucket`も付けよう(小並感)