I'm configuring an environment with a Amazon S3 Bucket for storage of media files and Amazon CloudFront for restricted distribution purposes.
The access to those media files needs to be private and should be done via a signed URL. So I created the S3 Bucket on South America (São Paulo)
region and uploaded some test files. Then I created a CloudFront Distribution with that previous bucket as Origin
and it's Bucket Access
is restricted. I created a new OAI (Origin Access Identity) and also selected the option Yes, Update Bucket Policy
so that it auto-configures the S3 Bucket Policies
.
I'm only using the default Behavior
and it's configured with HTTP and HTTPS
viewer protocol policy and GET, HEAD
allowed methods. Restrict Viewer Access (Use Signed URLs or Signed Cookies)
is set and the Trusted Signer
is set to Self
.
Here's some images to clarify the setup:
S3 Bucket Policy
Distribution's Origin
Distribution's Behavior
I'm getting a HTTP 403
while trying to access the signed URL generated with either awscli or cfsign.pl
<Error>
<Code>AccessDenied</Code>
<Message>Access denied</Message>
</Error>
Is there something missing that I don't know? It looks like I made everything the docs said to do.
If the web browser or curl command returns an Access Denied error, then the object isn't publicly accessible. To allow public read access: Create a bucket policy that allows public read access for all objects in the bucket. Use the Amazon S3 console to allow public read access for the object.
You got this error because you restricted your country to access your CloudFront. You have to change your restrictions in the Distribution file.
I received the same Access Denied
error and spent the last couple hours trying to figure out what was going on. I finally realized that the Expires
parameter was set in the past since I was using my local time instead of UTC. Make sure to set the Expires
in the future according to UTC.
In my case the problem was with URL I was passing to URL signing code (I was using AWS SDK for Node.js).
cloudFront.getSignedUrl({
url: `${distributionUrl}/${encodeURI(key)}`,
expires: Math.floor(new Date().getTime() / 1000) + 60 * 60
})
Note encodeURI
. I was not doing that. The resulting signed URL would still have URI components encoded, BUT would have invalid signature, thus causing 403 error.
EDIT: ...And you have to wrap it into url.format()
like this:
cloudFront.getSignedUrl({
url: url.format(`${distributionUrl}/${encodeURI(key)}`),
expires: Math.floor(new Date().getTime() / 1000) + 60 * 60
})
I guess they should be doing that in SDK.
After recreating both the Amazon S3 Bucket and Amazon CloudFront Distribution I was still experiencing the issue. After a session with my rubber duck I found out that the Private Key
file that I was using belongs to a deleted CloudFront Key-pair
.
Now that I'm using the correct key to encrypt things everything is working fine. That doesn't explain why the first bucket and distribution weren't working because in that specific case I was using the same set of configurations and the right Private Key
file.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With