3

I would like to add a query string parameter to my Cloudfront Url to be able to get some additional info into the Cloudfront log. I have two distributions, one is signed and one is not signed, pointing to two different S3 buckets (one with audio, one with images). Access to both distributions works fine without added query strings, but if I add a query parameter like the test one below:

https://x.cloudfront.net/audio.m4a?li=...62&Expires=1544430879&Signature=...QTQ__&Key-Pair-Id=xxx&test=fail

https://y.cloudfront.net/image.jpg?test=allgood

The first one fails (Access Denied) but the second one works fine. Neither one of the distributions forwards the query string to S3.

The signed audio distribution has logging enabled while the image distribution doesn't have logging. Besides this, their setups are the same.

What do I need to do in order to get the audio distribution to accept my custom query parameter? Thanks /o

jola
  • 977
  • 2
  • 10
  • 31
  • So what is your question exactly: how to forward the query strings to S3 or how to make S3 accept them? – AlexK Dec 10 '18 at 09:27
  • Sorry if unclear, but the question is how to get Cloudfront to accept a query string and not return an "Access Denied" response. – jola Dec 10 '18 at 11:00
  • Yes, the object do exist, requesting it without a custom query parameter works fine but if I add a parameter (like the test one in my example above) I get Access Denied. There is no need for me to modify the "forwarded query strings" setting since I do not need the query to go to S3, I only need it to be captured by Cloudfront's access logs, which it should even without forwarding, according to https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/QueryStringParameters.html And (jfyi) changing it on an existing distribution works fine (although I don't need to do it :-) – jola Dec 10 '18 at 12:18
  • Refer to this. Hope it helps. https://stackoverflow.com/questions/54965779/how-to-configure-query-params-in-aws-cloudfront – Nagarajan S R May 23 '21 at 20:31

3 Answers3

7

One of the core concepts behind signed URLs is that they are not vulnerable to tampering -- you can't change a signed URL and have it remain valid.

CloudFront uses the public key to validate the signature and confirm that the URL hasn't been tampered with. If the signature is invalid, the request is rejected.

...

Signed CloudFront URLs cannot contain extra query string arguments. If you add a query string to a signed URL after you create it, the URL returns an HTTP 403 status.

https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-signed-urls.html

To add a query string parameter to a CloudFront signed URL, you need to add it before signing the URL... because the addition will change the signature.

Michael - sqlbot
  • 169,571
  • 25
  • 353
  • 427
  • Thank you, that explains it! It would be good for Amazon to clarify this in their documentation though. They say (in the context of web apps appending query strings): "If you're using signed URLs and you want to configure CloudFront to forward query strings to your origin, your own query string parameters cannot be named Expires, Key-Pair-Id, Policy, or Signature." This gave me the idea it could be done client side. I will try to set a cookie instead which then hopefully gets tracked in the Cloudfront log. – jola Dec 10 '18 at 15:22
0

Consider using Cloudfront Functions and modifying HTTP response object to trigger a redirect [1].

Here is an example. This code checks whether there is a tmqff parameter in the url. If not, it adds the parameter to the url and makes a 302 redirect.

function handler(event) {
  var request = event.request;
  var headers = request.headers;
  
  if (request.querystring["tmqff"]) {
      return request;
  } else {
      var newUrl = "https://" + headers["host"].value + request.uri + "?tmqff=1"
    var response = {
        statusCode: 302,
        statusDescription: 'Found',
        headers:
            { 
                "location": { "value": newUrl} 
            }
        }

    return response;
  }
}

You should associate this as "Viewer Request" with your distribution.

Note that, this code swallows existing query string parameters in the url.

[1] https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/example-function-redirect-url.html

Halil
  • 1,795
  • 1
  • 24
  • 39
-1

Additional/Optional parameters can be allowed for a signed cloudfront URL by appending an asterisk (*) to the resource in the signature policy.

For example, if you sign the URL: https://example.com/images/funny/cat.png* then you will be able to add optional parameters to the URL.

If the parameters should not be optional you could also sign it like this: https://example.com/images/funny/cat.png?w=*&h=*. This way the values of the w and h params may be anything but both parameters must be set.

patrickd
  • 186
  • 1
  • 12