In my last post, I looked at how you can use the AWS SDK to upload images to Amazon S3 (Simple Storage Service). The only problem is that the storage bucket is private by default. If you try and access your image, even through the AWS interface, you get the following error:
You can make the individual files public – but this is hardly a practical solution for a web site with dynamically uploaded images. I want to have all the images be public by default – not to have to write code to make them public one by one:
Fortunately, it is possible to make your bucket public by default. Right click on the bucket and select properties.
This will open a new pane showing the permission options. Click on Add Bucket Policy to open the bucket policy window:
Then, inside the modal window, click on the AWS Policy Generator link:
The generator requires you to fill out a form and then writes a policy for you. The only complications are 1) deciding what permissions to allow and understanding what the options mean (for reading your images you want to expose ‘GetObject’), and 2) what your ARN name is. This is in the form arn:aws:s3:::<bucket_name>/<key_name>. In my case, that means arn:aws:s3:::cocktailsrus/*.
Here is the form:
Once you click “Add Statement” you’re given a button to Generate Policy – and that generates the policy text for you to paste into your bucket policy:
Once you’ve saved this policy, clicking on the link in the online tool shows you the image. All the images in your bucket are now public.
Unfortunately, that means EVERYONE can see them – including search engines and other web sites. I know S3 is cheap, but I still don’t like the idea of paying the fees for search engines or other websites showing my images. So how do I stop them?
We can stop the search engines easily enough with a standard robots.txt file in the bucket telling them not to index its contents:
Now all we have to do is stop hot-linking so we’re not paying for someone else’s use of our images. The answer to this is to refine the policy file so that it only serves images to people who are coming from (in my case) www.cocktailsrus.com. Sadly, the AWS policy generator isn’t much help with this, as it doesn’t seem to include an option to test against the referring web site. But while it’s not in the generator, there does seem to be such an option. I found the solution here and implemented it on my bucket.
Now, if I try and access my Ajax loader image via the link in the AWS online tool (i.e. NOT via cocktailsrus), I get the familiar XML message:
But if I access it via a test page on cocktailsrus.com, I get the image:
So, the images are now public, but only work if accessed via cocktailsrus.com – and I have a solution that will work when I move over to a web farm, unlike storing images to the file system.
For related information, check out these courses from Learning Tree: