7

Following is what I'm doing. I'm generating a pre-signed URL using a custom domain for my s3 bucket resources which are not public.

https://files.customdomain.com/file123?AWSAccessKeyId=XXX&Expires=1541220685&Signature=XXXX

Also to add the certificate I've created a cloudfront distribution for the bucket having following origin settings

Origin Domain Name: bucket-name.s3.amazonaws.com Origin Id : s3.bucket-name Restrict Bucket Access: No

Yet I'm unable to access my resources. Throws access denied error. Any help would be appreciated.

Yohan
  • 379
  • 1
  • 5
  • 14

4 Answers4

8

There are two cases:

  1. If your bucket has regular name.

In this case you should use CloudFront to access your bucket. And like mentioned above URL looks like in this answer:

https://cloudfront-url/file123?AWSAccessKeyId=XXX&Expires=1541220685&Signature=XXXX

  1. If your bucket has s3 static website name.

In this case your bucket name looks like files.customdomain.com and you can generate pre-signed url for this bucket:

https://files.customdomain.com/file123?AWSAccessKeyId=XXX&Expires=1541220685&Signature=XXXX

In your DNS you will have CNAME files.customdomain.com points to files.customdomain.com.s3.[bucket-region].amazonaws.com.

NOTICE

When I generate pre-signed URL via aws-cli:

aws s3 presign s3://files.customdomain.com/file123 --endpoint-url https://files.customdomain.com

I get URL with duplicate bucket name in the path: https://files.customdomain.com/files.customdomain.com/file123?AWSAccessKeyId=XXX&Expires=1541220685&Signature=XXXX

instead of:

https://files.customdomain.com/file123?AWSAccessKeyId=XXX&Expires=1541220685&Signature=XXXX

I don't know if it has the same behavior via SDK.

Dmytro F
  • 81
  • 1
  • 2
4

Have you tried initializing S3 with the custom url var S3 = new AWS.S3({endpoint: 'media.domain.com', s3BucketEndpoint: true}); More info https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html Also, make sure signature is correct as well https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingAWSSDK.html#specify-signature-version Ref : https://github.com/aws/aws-sdk-js/issues/891

Yves M.
  • 29,855
  • 23
  • 108
  • 144
3

When using S3 with CloudFront, you don't want an S3 signed URL... you want a CloudFront signed URL.

Read Configuring Security and Limiting Access to Content in the CloudFront developer guide.

Michael - sqlbot
  • 169,571
  • 25
  • 353
  • 427
  • No I need a s3 signed URL as I've added in the question. But as the custom end point i had to provide cloudfront url. Thanks for your help that gave me a hint. – Yohan Nov 03 '18 at 15:47
2

I found a solution for this question. The signed url needs to be generated for cloudfront url endpoint from s3 bucket. Therefore instead of
https://files.customdomain.com/file123?AWSAccessKeyId=XXX&Expires=1541220685&Signature=XXXX
it needs to be
https://cloudfront-url/file123?AWSAccessKeyId=XXX&Expires=1541220685&Signature=XXXX

and DNS records had to resolve custom domain to cloudfront url.

Yohan
  • 379
  • 1
  • 5
  • 14
  • 3
    This works, mostly by accident, but it will "work" as long as you understand a couple of important limitations: (1) it only works if the bucket is in one of the older (pre-2014) AWS regions like Ireland & Virginia, not newer regions like London & Ohio... and (2) all of your requests will be cache misses unless the *identical* signed URL (same key, expires, and signature) is reused by multiple clients. CloudFront can't allow different S3 signed URLs to be served from cache because it can't verify the authentication, so it has to forward every unique URL all the way back to S3 when first used. – Michael - sqlbot Nov 03 '18 at 16:25
  • I see. really thanks for the info. The solution I was looking for is something as above in my specific scenario. But your way is the most accurate way as it seems. Thanks again. – Yohan Nov 03 '18 at 17:33