我使用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!
注意,“未找到!”启用S3网站托管时,字符串来自桶属性上设置的错误文档。
我也尝试直接使用存储桶网址
的http://.s3.amazonaws.com/
并且返回相同的内容,除了我得到一个XML文档而不是错误文档
如何解决这个问题?
答案 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与GetObject
和ListBucket
一样,如图所示
{
"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"
]
}
]
}