2

Currently I have an S3 Bucket with an access policy that only allows access from a CloudFront Origin Access Identity:

{
    "Version": "2012-10-17",
    "Id": "PolicyForCloudFrontPrivateContent",
    "Statement": [
        {
            "Sid": "Grant a CloudFront Origin Identity access to support private content",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity XXXXXXXXXX"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::my-bucket/*"
        }
    ]
}

This should prevent any access to the S3 asset which is not through the CloudFront distribution.

However when I input the S3 url into my web browser I can still access the file.

I am using Carrierwave and Fog to upload files to S3 and have config.fog_public = true so I believe what is happening is that Fog is putting a public access setting on the uploaded object.

I tried changing the setting to config.fog_public = false but that then started returning signed URL's that ignored my asset_host setting (so provided the signed S3 URL rather than the unsigned CloudFront URL).

I presume I need to keep config.fog_public = true and have an S3 bucket policy that overrides the public access setting that Fog is putting on my objects.

Can anyone advise if that is correct or is there a better approach?

Betjamin Richards
  • 1,071
  • 2
  • 12
  • 34

2 Answers2

3

TLDR: You should set fog_public to false, to ensure the files are private outside your other settings. Then, instead of calling url, which differs based on the fog_public setting, call public_url which should always return asset_host style urls.

Details:

config.fog_public = true does 2 things:

  1. set public readable when the files are created
  2. return public-style urls for reading

whereas config.fog_public = false does two different things:

  1. set public readable to false when files are created
  2. return private/signed-style urls for reading

Unfortunately you want 1/2 of each approach, which the url within carrierwave doesn't directly support.

I think you will probably want to leave config.fog_public = false in order to ensure the files are private as you desire, but you may have to get the urls differently in order to have them show up with the seemingly public urls you desire. Normally the usage of carrierwave suggests you should use url to get what you want, and this has branching logic based on the fog_public setting. You can skip over this logic and just get the asset_host url though, by just calling public_url instead.

All that said, out of my own curiosity, if the files will be publicly available via CDN anyway, why would they need to be private via S3?

geemus
  • 2,522
  • 16
  • 22
0

Here you can see how to configure per model (one public, another private): https://stackoverflow.com/a/18800662/5945650

Community
  • 1
  • 1