绕过 x-amz-cf-id header 包含在云端 S3 身份验证中的需要

Bypassing need for x-amz-cf-id header inclusion in S3 auth in cloudfront

我有一个不完全正统的 CF->S3 设置。这里的相关组件是:

  1. Cloudfront 分布 origin s3.ap-southeast-2.amazonaws.com

  2. 添加 S3 授权(版本 2)查询字符串(使用函数使用的 S3 策略签名)的 Lambda@Edge 函数(原始请求)。

Lambda返回的请求完全正确。如果我记录 uri、主机和查询字符串,我会得到我请求的文件。但是,如果我直接通过 Cloudfront link 访问它,请求将失败,因为它不再使用 AWSAccessKeyID,而是选择使用 x-amz-cf-id(但使用相同的签名,Amz-Security-Token 等)。 更正:它可能不会取代,但除此之外还需要。

我知道是这种情况,因为我已经退回了 StringToSignSignatureProvided。除了 AWSAccessKeyID 已替换为 x-amz-cf-id.

之外,它们都与 Lambda 响应匹配

这显然是一个非常具体的问题。我可能不得不考虑重塑这个架构,但我不想这样做。有几个要求让我失望了这个不完全正常的设置。

因此,对于身份验证 V2 或 V4,附加到原始请求且 Lambda@Edge 原始请求函数无法访问的 x-amz-cf-id header 似乎必须包含在身份验证字符串中。这是不可能的。

简单的解决方案是使用 Cloudflare 中的 built-in S3 集成,如果像我一样使用 Lambda@Edge 源请求函数来切换存储桶,这就是您想要的目标。对于您要使用的每个存储桶,添加以下策略以允许您的 CF 分发访问存储桶中的 objects。

{
    "Version": "2008-10-17",
    "Id": "PolicyForCloudFrontPrivateContent",
    "Statement": [
        {
            "Sid": "1",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity <CloudfrontID>"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::<bucket-name>/*"
        }
    ]
}

CloudfrontID 是指 Origin Access Identity 下的 ID,而不是 Amazon S3 Canonical ID .

我相信 AWSAccessKeyID => x-amz-cf-id 替换是两种机制的结果:

首先,您需要配置 CloudFront 以将查询参数转发到源。否则,它将去除所有参数。如果您使用 S3 签名 URL,请确保还基于所有参数进行缓存,否则您最终将没有任何访问控制。

其次,CloudFront 将 x-amz-cf-id 附加到不去往 S3 源 的请求 。您可以在 CloudFront 控制台仔细检查源类型,您需要确保它被报告为 S3。我有一个 blog post 详细描述它。

但是使用 Lambda@Edge 向所有请求添加 S3 签名达不到目的。如果您想将存储桶保密并只允许 CloudFront 访问它,那么请使用 Origin Access Identity,这正是该用例。

X-amz-cf-id 是 CF 的保留头,可以通过事件获取,如 event['Records'][0]['cf']['config' ]['requestId']。您不必使用 X-amz-cf-id 计算 Authentication V4。