如何为存储桶中不存在的密钥返回404(而不是403)S3桶

fer*_*oze 44 amazon-s3

我使用S3来存储一些关键业务文档.我希望存储桶在尝试访问存储桶中不存在的对象时返回404状态代码.

但是,我发现它一直让我回归"403

这是使用S3网站URL的会话示例.

> GET /foobar.txt HTTP/1.1
> User-Agent: curl/7.21.6 (x86_64-pc-linux-gnu) libcurl/7.21.6 OpenSSL/1.0.0e zlib/1.2.3.4 libidn/1.22 librtmp/2.3
> Host: <bucketname>.s3-website-us-east-1.amazonaws.com
> Accept: */*
> 
< HTTP/1.1 403 Forbidden
< Last-Modified: Mon, 09 Sep 2013 19:10:28 GMT
< ETag: "14e13b81b3ce5b129d1f206b3e514885"
< x-amz-error-code: AccessDenied
< x-amz-error-message: Access Denied
< x-amz-request-id: <snip>
< x-amz-id-2: <snip>
< Content-Type: text/html
< Content-Length: 11
< Date: Thu, 26 Sep 2013 20:01:45 GMT
< Server: AmazonS3
< 
Not found!
Run Code Online (Sandbox Code Playgroud)

注意,"未找到!" 启用S​​3网站托管时,字符串来自桶属性上设置的错误文档.

我也尝试直接使用桶URL访问

HTTP://.s3.amazonaws.com/

除了错误文档而不是错误文档之外,我得到一个XML文档

我该如何解决这个问题?

Tim*_*ier 66

当用户没有列出存储桶内容的权限时,S3返回403而不是404.

如果查询对象并接收404,则表示该对象不存在.如果您没有权限列出存储桶内容,这是您不应该知道的信息,而不是告诉您它不存在,S3只是告诉您,您正在尝试做一些您不允许做的事情.当你得到403而不是404时,你无法知道你请求的对象不存在.它可能不存在或可能存在,您只是无权访问它.您无法确切知道,因此不会绕过任何安全措施.

我相信有权访问列出存储桶内容的人将获得404而不是403.

  • 以下是解释如何使用 AWS 控制台添加列表权限的答案:http://stackoverflow.com/a/32398826/682317 (4认同)

Pet*_*erg 26

确切的要求似乎是您的用户拥有ListBucket您的特定存储桶的权限,并且ARN正是表单的形式arn:aws:s3:::your_bucket_name.

我还需要在我的策略中添加一个全新的语句,因为其他权限GetObject仍然要求ARN以/*或其他一些合适的通配符结束.

{
  "Action": [
    "s3:ListBucket"
  ],
  "Sid": "StmtNNNNNNNNNNNNNNNwholebucket",
  "Resource": [
    "arn:aws:s3:::your_bucket_name"
  ],
  "Effect": "Allow"
},
Run Code Online (Sandbox Code Playgroud)

总而言之,对我来说重要的一点是,如果ARN不是arn:aws:s3:::your_bucket_name/*ListBucket 的形式,或者你仍然会得到403而不是404.


小智 14

Not Sure if you're looking for this. Making your objects public to everyone solves the 404 issue. However, I do not believe that it is the ideal way to go through with it.

AWS Cloudfront provides a feature called Origin Access Identity (OAI). How it works is given in detail here.

Basically in a nutshell, Associate an OAI with your Origin in Cloudfront and update the bucket policy to allow the OAI with GetObject and ListBucket as shown

{
  "Version": "2008-10-17",
  "Statement": [
    {
      "Sid": "AllowOAIRead",
      "Effect": "Allow",
      "Principal": {
        "AWS": [
          "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity your_OAI_ID"
        ]
      },
      "Action": [
        "s3:GetObject",
        "s3:ListBucket"
      ],
      "Resource": [
        "arn:aws:s3:::your_bucket_name/*",
        "arn:aws:s3:::your_bucket_name"
      ]
    }
  ]
}
Run Code Online (Sandbox Code Playgroud)

  • 这是正确的答案。其他人让它变得脆弱。 (5认同)
  • 该答案应标记为最佳答案 (3认同)

Mat*_*ieu 6

确保你的权限EveryoneView Permissions.

您可能还想添加存储桶策略:

{
    "Version": "2008-10-17",
    "Statement": [
        {
            "Sid": "PublicReadGetObject",
            "Effect": "Allow",
            "Principal": {
                "AWS": "*"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::your_bucket_name/*"
        }
    ]
}
Run Code Online (Sandbox Code Playgroud)

  • 使用存储桶策略意味着您不需要每个人的权限。 (2认同)

小智 6

我需要像这样扩展策略:

 "Action": [
   "s3:Get*",
   "s3:List*"
 ],
 "Resource": [
   "arn:aws:s3:::bucket_name",
   "arn:aws:s3::: bucket_name/*"
 ],
Run Code Online (Sandbox Code Playgroud)

bucket_name是必需的,因为如果没有它,您不会得到缺少对象的404,但bucket_name/*实际上需要403 才能真正访问存储桶中的内容。

  • 这些操作通配符提供的权限比大多数人需要的要广泛得多。其他答案提到专门为 s3:ListBucket 添加单独的语句,这是更好的安全实践。 (4认同)