Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AWS CloudFront with Signed URL: 403 Access Denied

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 S3 Bucket Policy

Distribution's Origin Distribution's Origin

Distribution's Behavior 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.

like image 641
Daniel Faria Sampaio Avatar asked May 04 '17 17:05

Daniel Faria Sampaio


People also ask

Why is CloudFront Access Denied?

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.

Why is Amazon CloudFront blocking me from websites?

You got this error because you restricted your country to access your CloudFront. You have to change your restrictions in the Distribution file.


3 Answers

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.

like image 176
ameier38 Avatar answered Oct 19 '22 07:10

ameier38


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.

like image 45
Wicharek Avatar answered Oct 19 '22 06:10

Wicharek


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.

like image 24
Daniel Faria Sampaio Avatar answered Oct 19 '22 05:10

Daniel Faria Sampaio