phpsymfonyamazon-s3liipimaginebundle

Amazon S3 Policy + Liip Imagine Cache Resolver


I have set up an Amazon S3 cache resolver with the Liip Imagine bundle, and having issues getting the right permissions set on the bucket to prevent directory content listing in the browser.

My Scenario:

The site has quite a few image assets on S3 - some manually uploaded and many also uploaded via CMS using the Vich Upload bundle. I use the Imagine bundle to resolve cached images based on filters defined in the config.yml file (for things like thumbnails and previews) which are then stored in separate directories in my S3 bucket named after the filter. So in short, Upload original to S3 -> resolved cached files stored on S3 automatically. Works great.

The Problem

The only way I've been able to resolve the cached files when requested the first time is to have wide open public permissions on the bucket. This is not good because when you do this S3 exposes a "bucket explorer" in the way of an XML file that lists the entire buckets contents (or at least the first 1000 records). I need all the files to be public, but I can't have a list of them out there at any given time because we've had issues with people sniffing this clients site prior to new product launches. I at least don't want a list of file names out there.

What I've Tried

I've tried several combinations of settings in the bucket ACL in combination with the following bucket policy:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AddPerm",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::[MY_BUCKET]/*"
        }
    ]
}

And what I've found is that the cached files will not resolve unless the "Everyone" group under public access is given "List objects" permissions. As soon as I turn off that permission (which disables viewing of the XML file in the browser) uncached files can no longer be resolved from the uploads.

enter image description here

What else I've tried

I also tried configuring the bucket as a website and uploaded a default index.html file in the root, per some suggestion I found here. This did nothing. Maybe I'm missing something.

I also tried ensuring the cache resolve folders were public within S3 with the list Objects permission turned off in the bucket. This did not work either.

The Error

When the list objects permission is removed the following error is produced when the resolve attempt takes place

Error executing "CreateBucket" on "https://[MY_BUCKET].s3.amazonaws.com/"; 
AWS HTTP error: Client error: `PUT https://[MY_BUCKET].s3.amazonaws.com/` 
resulted in a `403 Forbidden` response:

<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>AccessDenied</Code>
<Message>Access Denied</Message><RequestId>94D939 (truncated...)
AccessDenied (client): Access Denied - <?xml version="1.0" encoding="UTF-8"?>
<Error><Code>AccessDenied</Code><Message>Access Denied</Message>
<RequestId>[HIDDEN]</RequestId>
<HostId>[HIDDEN]</HostId>
</Error>

Bucket Structure is like this

[MY_BUCKET]
  -thumbnails // <-- where thumbnails are resolved
  -previews // <-- where previews are resolved
  -uploads  // <-- primary uploads parent dir
  --products // <-- where products are uploaded
  --other // <-- where other files are uploaded
  --images // <-- where images are manually uploaded

My assumption is that the resolver needs to read the contents of the directories in order to determine if the file has been resolved or not.

If necessary, I can provide config information from symfony, but I'm not having issues with that so didn't think it would be necessary.

Ultimately I just need to be able to let the resolver do its thing and prevent browser access to the bucket contents.


Solution

  • I figured this out. It required an adjustment on the policy at the IAM level, changing the resource node from:

    ...
    "Resource":[
        "arn:aws:s3:::[MY_BUCKET]/*"
    ]
    

    to:

    ....
    "Resource":[
        "arn:aws:s3:::*"
    ]