Configuring Amazon S3 to Serve Images

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:

access denied xml

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:

make public option

Fortunately, it is possible to make your bucket public by default. Right click on the bucket and select properties.

bucket properties link

This will open a new pane showing the permission options. Click on Add Bucket Policy to open the bucket policy window:

properties details

Then, inside the modal window, click on the AWS Policy Generator link:

bucket policy editor

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:

bucket policy generator

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:

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:

User-agent: *

Disallow: /

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.

refined bucket policy

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:

denied by non-referral

But if I access it via a test page on cocktailsrus.com, I get the image:

working 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.

Kevin Rattan

For related information, check out these courses from Learning Tree:

Cloud Computing with Amazon Web Services

Building Web Applications with ASP.NET MVC

Type to search blog.learningtree.com

Do you mean "" ?

Sorry, no results were found for your query.

Please check your spelling and try your search again.