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:
Amazon S3 invokes the CreateThumbnail function for each image file that is uploaded to an S3 bucket. The function reads the image object from the source S3 bucket and creates a thumbnail image to save in a target S3 bucket. First, you need to create S3 Bucket. Then Create a Folder inside your S3 Bucket. Upload the images in this folder you want to see in the browsers. You can upload the image directly in S3 bucket also if you are not creating a folder. Lazy Amazon S3 Image processor by Cuatromedios. If you don't want to proccess an image once uploaded because you don't know what sizes you will need in the future then this script is for you. Takes an image from an Amazon S3 bucket, process it, and then stores the result in another bucket. To see that image you uploaded in the S3 bucket that was created for you, choose the Resources button on the left-hand navigation of the Mobile Hub console, choose the link in the tile labeled Amazon S3 buckets to open the Amazon S3 console, then choose the Public folder.
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:
Amazon S3 Image Storage
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.
Amazon S3 Image Access Denied
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:
Amazon S3 Image
But if I access it via a test page on cocktailsrus.com, I get the image:
Amazon S3 Image Hosting
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: