-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
s3.getSignedUrl() with custom domain and path via CloudFront #1753
Comments
...oh, the CloudFront behavior path pattern is not a prefix that is removed - the path is not (can not) be rewritten by CloudFront - that's a shame |
It looks like CloudFront is forwarding the request path (including the signature parameters in the query string) on to S3 but overwriting the host. This is expected behavior for CloudFront — it’s meant to act as a caching proxy whose DNS record is distinct from that of the backend to which it forwards requests — so I’m not sure it would be possible to access a presigned S3 URL through a CloudFront web distribution. CloudFront has its own presigning mechanism that you might want to look into. The developer guide for the feature can be found here, and the API docs for the AWS SDK for JavaScript’s CloudFront presigner can be found here. Because CloudFront presigning uses RSA private keys, it is only available server-side and is not supported in the browser SDK. |
@jeskew for what it's worth... it's technically "possible" but it's awkward, rarely useful, and not the intended solution. Here's what's required:
Some of these steps seem counter-intuitive, particularly the idea of modifying a pre-signed URL without invalidating it -- but it works because you're modifying the URL in such a way that it's valid after CloudFront modifies it (again) such that it will match the canonical request that was originally signed. You're basically tweaking the signed URL so that it's for the final request, not the initial one, and then modifying the result to match what CloudFront is expecting. When you are done, you end up with a signed URL that will "work," but when actually used, it results in CloudFront caching responses that it will never again actually serve from the cache... unless you're actually reusing that exact same identical signed URL, signature and all (unlikely). This is because CloudFront (correctly) uses the entire forwarded request -- including the forwarded query string -- as the cache key used when doing a cache lookup. So they requests will always be The net result of this approach is that you end up with something very similar to S3 Transfer Acceleration -- you're transporting the request on the AWS "edge network," which may speed up transfers (particularly to viewers more distant from the bucket), but not actually doing any caching. This also requires that the distribution be configured without an origin access identity, and with "Restrict Viewer Access" set to disabled, because CloudFront isn't an active participant in the authentication -- it just passes through the requests. Without the signature, S3 will still deny the requests if the bucket and objects aren't public. Using the CloudFront signing solution is definitely the way to go, except perhaps in rare cases. |
Thanks for the deep dive on that, @sqlbot! It didn't occur to me that even if you could get S3 presigned URLs to work, using them would make nearly all requests uncacheable. @nalbion, I would strongly recommend using CloudFront's presigning mechanism. In addition to avoiding the complexity described above, CloudFront will be able to cache objects based on their identifiers (bucket name + key name) rather than on the exact signature used. |
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs and link to relevant comments in this thread. |
I'm trying to use
s3.getSignedUrl()
to download a file '1234.txt
' from S3 'my-download-bucket
'.Some users are behind proxies which do not allow access to
*.amazonaws.com
, so I'm trying to use CloudFront to map the S3 originmy-download-bucket.s3.amazonaws.com
with a behavior path patterndownloads/*
. With DNS mapping the CloudFront distribution tofiles.mydomain.com
users should be able to downloadhttps://files.mydomain.com/downloads/1234.txt
(with extra params provided bygetSignedUrl()
)(I also have an upload bucket which is mapped to the default path of the CloudFront distribution, and everything is working well there)
The code above generates the URL as desired, and it seems that the request is being passed through to
my-downlod-bucket
but an error is returned:2 things stand out to me:
GET /downloads/1234.txt
should beGET /1234.txt
as far as the bucket is concernedhost:my-downlod-bucket.s3.amazonaws.com
befiles.mydomain.com
?The text was updated successfully, but these errors were encountered: