Making files public in Amazon S3 and the owner problem

The most common way to make files publicly accessible for an Amazon S3 bucket is to add a bucket policy (Bucket Properties -> Add Bucket Policy).

{
  "Version":"2008-10-17",
  "Statement":[{
    "Sid":"AllowPublicRead",
        "Effect":"Allow",
      "Principal": {
            "AWS": "*"
         },
      "Action":["s3:GetObject"],
      "Resource":["arn:aws:s3:::bucket/*"
      ]
    }
  ]
}

As you should expect, you would replace “bucket” in the resource line to the name of your bucket- the syntax is actually quite familiar, using an asterisk as a wildcard parameter for all files inside of the specified bucket.

This still leaves some people in trouble though, because the bucket policy only applies to files that are owned by the bucket’s administrator. If you have an external application uploading files to your bucket, the policy does not apply, and you could be left with private/unaccessible files. There is a Stack Overflow post that explains this in a bit more depth.

Since my application is already using the Ruby Library for Amazon S3, the easiest solution was to change the policy for the file itself.  The solution is not very clear or elegant in the librarie’s documentation, so here is the best way.

#get the amazon object
amazon_object = AWS::S3::S3Object.find('golden_gate_bridge.png', 'my_photo_bucket')
#grant a public_read policy to the object grants
amazon_object.acl.grants << AWS::S3::ACL::Grant.grant(:public_read)
#write the changes to the policy
amazon_object.acl(amazon_object.acl)

The last way to get public access to a private file is to create a public url for the object, which defaults to only being accessible for 5 minutes, but can be set to a time in the future that is likely beyond the needs of your application. The documentation outlines a “doomsday” example.

doomsday = Time.mktime(2038, 1, 18).to_i
url = amazon_object.url(:expires => doomsday)

Using this method exposes three URL paramters in the public url- “AWSAccessKeyID”, “Expires”, and “Signature”, which junks it up a bit. Check up on the docs for more, and if you are just getting started with Ruby and Amazon S3, one of my previous posts might be of some help.