使用未签名的 URL 访问 public-read S3 对象时,我是否应该收到 Cloudfront ‘MissingKey’ 错误?

Should I be getting a Cloudfront ‘MissingKey’ error when using an unsigned URL to access a public-read S3 object?

假设我正在构建一个 Dropbox 克隆:Filebox。我使用 S3 存储我所有用户的文件,我使用 Cloudfront 作为我的 CDN。

所以我有一个受限的 S3 存储桶 (files.filebox.com),它的存储桶策略允许 s3:GetObject 我创建的 Origin Access Identity通过云端。这会强制所有 'file' 请求通过 Cloudfront 并禁止任何人通过 S3 URLs 访问文件。


files.filebox.com

的存储桶策略
{
    "Version": "2008-10-17",
    "Id": "AllowCloudfrontGet",
    "Statement": [
        {
            "Sid": "AllowCloudFrontGet",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity XXXXXXXXXXXX"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::files.filebox.com/*"
        }
    ]
}


意外行为

假设,为了简单起见,我使用 public-read.

的固定 ACL 存储所有文件

所以这个 URL 应该有效:
https://files.filebox.com/<userID>/some-file.txt

但是这个应该会导致 403: https://s3.amazonaws.com/files.filebox.com/<userID>/some-file.txt

但我看到了相反的结果。 S3 URL 工作正常,但正在通过 Cloudfront 的 files.filebox.com URL 抛出 MissingKey 错误。

files.filebox.com URL 确实 有效,但前提是我签署 URL,即使对于 ACL 为 public-read.


问题

鉴于存储桶策略仅允许 s3:GetObject 用于 CF OAI,即使对象具有 public-readACL?
我在文档中找不到任何关于此的信息,除了模糊的语言似乎表明受限存储桶应该 403 对于 any 没有通过 Cloudfront 的请求。

当我将对象的 ACL 设置为 public-read 时,即使在受限存储桶上,是否也不需要签署 Cloudfront URL?

我是否需要向我的存储桶策略添加另一个 Statement 以允许未签名的 URL 访问 public-read 对象?
我尝试了这个,但没有用。我什至不确定如何写这样的 Statement ...

如何真正 拒绝任何通过 S3 URLs 发出的请求?
我想为通过 S3 URL 的 any 请求抛出 403,即使对于 ACL 为 public-read.[=29= 的对象也是如此]

Given that the bucket policy only allows s3:GetObject for the CF OAI, shouldn't the S3 URL fail with a 403, even if the object has a public-read ACL?

没有。 public-read 表示 public(未验证)直接从 S3 读取。因为存储桶拥有者允许使用 public-read ACL 上传对象,所以对象是 public 并且得到存储桶拥有者的默示同意,即使根本没有任何存储桶策略。

对象 ACL 和存储桶策略 Allow 选项是附加的。如果您不希望通过 S3 端点访问该对象,请不要将其设置为 public.

When I set the ACL of an object to public-read does that not obviate the need to sign the Cloudfront URL, even on a restricted bucket?

不,不是。 CloudFront 不评估对象 ACL。它根据缓存行为设置决定是否需要身份验证。如果配置为需要对给定路径模式进行身份验证,则它需要身份验证,无论 CloudFront 背后的实体是 S3 还是其他。如果 CloudFront 拒绝访问,则甚至不会向 S3 发送任何请求。

Do I need to add another Statement to my Bucket Policy that allows unsigned URL access to public-read objects?

没有。存储桶策略中的任何内容都不会修改 CloudFront 前端身份验证的行为。

典型的方法是将某些前缀指定为 public 而其他前缀则不指定,并使用适当的匹配路径模式配置 CloudFront 缓存行为,例如/public/* 可能配置为不需要签名 URL,但 /private/* 可能需要它们。

此设置称为 Restrict Viewer Access,并在缓存行为级别(因此在路径模式级别)设置。

I'd like to throw a 403 for any requests that come through on S3 URLs, even for objects with an ACL of public-read.

将对象 ACL 设置为 public-read 意味着,根据定义,该对象应该可以直接从 S3 存储桶端点访问而无需凭据。仅此而已。

从这个角度来看,你所说的类似于说 "I'd like to prevent someone from stealing my car, even though I am planning on leaving the keys in the ignition." 可以做到,但它解决了错误的问题......而且它很快变得复杂,因为你必须诉诸战术例如 DenyNotPrincipal 条件,不仅包括 CloudFront 的异常,还包括控制台中您自己以及访问存储桶的应用程序、角色等的异常。

Origin Access Identity 的意义在于,CloudFront 拥有一组可在向存储桶发送请求时使用的凭据,无论 CloudFront 是否要求用户提供身份验证凭据。有了 OAI,就没有理由在对象 ACL 上使用 public-read