AWS CloudFront Returns 使用查询字符串从 S3 源拒绝访问

AWS CloudFront Returns Access Denied from S3 Origin with Query String

我已经按照本文所述设置了 CloudFront 分配和 Lambda@Edge 函数:

https://aws.amazon.com/blogs/networking-and-content-delivery/resizing-images-with-amazon-cloudfront-lambdaedge-aws-cdn-blog/

我现在想将 S3 存储桶限制为私有,只允许 CloudFront 分发访问该存储桶。我已将源访问身份添加到 S3 源配置,并更新了存储桶策略以允许此 OAI GetObject 访问存储桶。我已从存储桶策略中删除了使其 public 可读的语句,并将 ACL 更改为私有。如果我在对 CloudFront 的请求中不包含任何查询字符串参数,图像将按预期返回,并且 S3 link 无法直接访问。

但是,该解决方案依赖于传递查询参数来动态调整图像大小(通过 2 个 Lambda@Edge 函数),并且在将存储桶设为私有后,我从 CloudFront 收到拒绝访问 403 响应。

我尝试禁用查询字符串的转发,但没有效果。我还尝试仅更新存储桶策略以删除 public 读取访问权限,并将 ACL 保留为 PublicRead 并且它起作用了。所以这让我觉得 ACL 设置为 private

有问题

我想知道当存储桶设为私有时,S3 是否返回 403 而不是 404?但是后来我不明白为什么添加白名单查询字符串参数会产生与没有查询字符串的相同图像的请求不同的结果

更新

工作示例URL:http://<my_distro>.cloudfront.net/images/house.jpeg

损坏示例URL:http://<my_distro>.cloudfront.net/images/house.jpeg?size=1200

调查后发现,如果存储桶是私有的,那么如果存储桶中不存在对象,S3 将 return 返回 403 而不是 404,这从安全角度来看是有意义的(防止对象枚举等)。

当存在查询字符串时,来自博客 post 的 Lambda 中的查看器请求代码转换了图像 url。如果此图像不存在,它会即时生成它。来自博客 post 的原始响应函数正在检查 404 状态以触发图像大小调整。但是,当存储桶设为私有时,响应为 403,因此 Lambda@Edge 只是转发响应。解决方法是处理 403 或创建存储桶 public。我和前者一起去了

Lambda@Edge 通过特殊用户与 s3 一起工作。 因此,您必须在 s3 存储桶策略中添加规则,如下所示:

{
    "Version": "2008-10-17",
    "Id": "PolicyForCloudFrontPrivateContent",
    "Statement": [
        {
            "Sid": "1",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity XXXXX"
            },
            "Action": [
                "s3:GetObject"
            ],
            "Resource": "arn:aws:s3:::xxx/*"
        },
        {
            "Sid": "2",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity XXXX"
            },
            "Action": [
                "s3:ListBucket"
            ],
            "Resource": "arn:aws:s3:::xxxx"
        }
    ]
}