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

时间:2013-09-26 20:04:47

标签: amazon-s3

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

然而,我发现它一直让我回归“403

以下是使用S3网站网址的会话示例。

> 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!

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

我也尝试直接使用存储桶网址

  

的http://.s3.amazonaws.com/

并且返回相同的内容,除了我得到一个XML文档而不是错误文档

如何解决这个问题?

5 个答案:

答案 0 :(得分:61)

当用户没有列出存储桶内容的权限时,

S3返回403而不是404。

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

我相信任何有权列出存储桶内容的人都会得到404而不是403。

答案 1 :(得分:24)

确切的要求似乎是您的用户对您的特定广告资源拥有ListBucket权限,而ARN的格式恰好是arn:aws:s3:::your_bucket_name

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

{
  "Action": [
    "s3:ListBucket"
  ],
  "Sid": "StmtNNNNNNNNNNNNNNNwholebucket",
  "Resource": [
    "arn:aws:s3:::your_bucket_name"
  ],
  "Effect": "Allow"
},

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

答案 2 :(得分:6)

确保您的权限Everyone中有View Permissions

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

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

答案 3 :(得分:3)

我需要像这样扩展政策:

var data = [{ Company: "Church Mutual", accountId: "1234567  ", accountName: "Test123", handlerId: "1111111  ", lineOfBusiness: "WC", selectedState: "NY", tpa: "No" }, { Company: "Church Mutual", accountId: "1234567  ", accountName: "Test123", handlerId: "1111111  ", lineOfBusiness: "WC", selectedState: "NY", tpa: "No" }],
    keys = ['accountId', 'handlerId'];

data.forEach(o => keys.forEach(k => o[k] = o[k].trim()));

console.log(data);

.as-console-wrapper { max-height: 100% !important; top: 0; }是必需的,因为没有它,丢失的对象将不会得到404,但总是403, "Action": [ "s3:Get*", "s3:List*" ], "Resource": [ "arn:aws:s3:::bucket_name", "arn:aws:s3::: bucket_name/*" ], 才是访问存储桶中内容的必要条件。

答案 4 :(得分:1)

不确定是否要寻找这个。将对象公开给所有人都可以解决404问题。但是,我认为这是完成它的理想方法。

AWS Cloudfront提供了一项称为Origin Access Identity(OAI)的功能。 detail here中给出了工作原理。

简而言之,将OAI与您在Cloudfront中的起源相关联,并更新存储桶策略,以使OAI与GetObjectListBucket一样,如图所示

{
  "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"
      ]
    }
  ]
}