Question:
I have a not completely orthodox CF->S3 setup. The relevant components here are:
- Cloudfront distribution with
origin s3.ap-southeast-2.amazonaws.com
- Lambda@Edge function (Origin Request) that adds a S3 authorisation (version 2) query string (Signed using the S3 policy the function uses).
The request returned from Lambda is completely correct. If I log the uri, host and query string I get the file I am requesting. However, if I access it through the Cloudfront link directly, the request fails because it no longer uses the AWSAccessKeyID
, instead it opts to use x-amz-cf-id
(but uses the same Signature, Amz-Security-Token etc). CORRECTION: it may not replace, but be required in addition to.
I know this is the case because I have returned both the
StringToSign
and the SignatureProvided
. These both match the Lambda response except for the AWSAccessKeyID
which has been replaced with the x-amz-cf-id
.
This is a very specific question obviously. I may have to look at remodelling this architecture but I would prefer not to. There are several requirements which has led me down this not completely regular setup.
Answer:
So it seems like with Authentication V2 or V4, the x-amz-cf-id
header that’s appended to the origin request and inaccessible by the Lambda@Edge origin request function must be included in the authentication string. This is not possible.
The simple solution is to use the built-in S3 integration in Cloudflare, use a Lambda@Edge origin request function that switches the bucket if like me, that’s your desired goal. For each bucket you want to use, add the following policy to allow your CF distribution to access the objects within the bucket.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
{ "Version": "2008-10-17", "Id": "PolicyForCloudFrontPrivateContent", "Statement": [ { "Sid": "1", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity }, "Action": "s3:GetObject", "Resource": "arn:aws:s3::: } ] } |
CloudfrontID
refers to the ID under Origin Access Identity, not the Amazon S3 Canonical ID.