When you decide to distribute your content stored in your Amazon S3 bucket with Amazon CloudFront, you most probably would like to avoid your users bypassing CloudFront and accessing them directly from Amazon S3.
In this blog post, I will demonstrate how you can utilize Origin Access Identities to restrict access to your S3 bucket on your Amazon CloudFront distributions.
What are Amazon S3 and Amazon CloudFront?
Amazon Simple Storage Service or S3, as you can understand from its name, is the storage service offered by Amazon Web Services. You can store all type of your static files; serve your static website like this blog or your serverless website on Amazon S3. It is scalable, 99.999999999% reliable and cost-effective. An S3 bucket is automatically replicated accross multiple availability zones in the AWS region it belongs to.
However, Amazon S3 is served from an AWS region and the speed of delivering content to your users is negatively effected by the destination of your users to the region. You can solve this problem using content delivery networks (CDNs) and Amazon CloudFront is the CDN service offered by AWS.
Amazon CloudFront is distributed all over the world through AWS edge locations and when a request is received for the content, it is served from the nearest edge location to the user if it was cached before. Actually, the first user accessing the content does not benefit from this speed, because the content was not cached before the request. However, the content is served from the cache to all subsequent users near this edge location. You define a time-to-live (TTL) value for your content to tell CloudFront when to refresh its cache by getting the content from Amazon S3 bucket. You can also distribute ontent from your webservers; however, I limit this post with Amazon S3 distributions.
What is an Origin Access Identity used for?
The problem with CloudFront distributions with default settings is that you make your bucket public and your users can also access your content through Amazon S3 bucket if they know the bucket address. This makes CloudFront’s caching mechanism ineffective. Besides, if you would like to serve your private content with signed urls through CloudFront, you need to allow access to your content only through CloudFront. Otherwise, unautharized users can access your content through Amazon S3 without your control.
To avoid this situation, you need to define an Origin Access Identity for your CloudFront distribution, make your bucket private and only grant access to this Origin Access Identity.
However, let me note that Origin Access Identity is only applicable to distributions who have Amazon S3 buckets as
Origin Domain Name. Unfortunately, you cannot use an Origin Access Identity on a distribution for a static website hosted on Amazon S3 which should have its S3 website address as the origin domain name.
How to create an Origin Access Identity
An Origin Access Identity is a special Amazon CloudFront user. You can create an Origin Access Identity while creating your CloudFront distribution.
The process is same for both web or RMTP distributions. After entering
Origin Domain Name as your S3 bucket, select
Restrict Bucket Access section revealed. It is under
Origin Settings if you are creating a web distribution or
RMTP Distribution Settings if you are creating a RMTP distribution. When you enable bucket restriction, be sure to select
Create a New Identity on
Origin Access Identity section. It has only
Comment field which you can leave as it is or type a meaningfull explanation to remember in the future.
Alternatively, you can create an Origin Access Identity in CloudFront console under
Private Content -> Origin Access Identity section.
Then, during CloudFront distribution creation select
Use an Existing Identity and select your newly created Origin Access Identity from the list.
Grant read access to Origin Access Identity
You created an Origin Access Identity, but it has no permissions. You need to grant it read access to your S3 bucket to be able to serve your users. Again, you can do this during creation by selecting
Yes, Update Bucket Policy in
Grant Read Permissions on Bucket section.
It actually modifies the bucket policy of your S3 bucket to grant read access to your Origin Access Identity as below.
If you need to grant read access to Origin Access Identity manually, then select
No, I Will Update Permissions. This time, you need to use
Principal in the bucket policy as below. You can find the Amazon S3 Canonical User Id of your Origin Access Identity on
Origin Access Idenitity.
After refreshing the bucket policy page, you will see that Amazon S3 converted your policy with CanonicalUser to the arn version automatically.
By default, only owner of the S3 bucket has access to objects in an Amazon S3 bucket. If you are modifying an existing bucket, please be sure to remove permissions on object access control lists (ACLs).
After creating your CloudFront distribution, you should wait for its status to switch from “In Progress” to “Deployed”. Then, your objects will only be distributed via CloudFront urls.
Attention for creating distributions for recently created S3 buckets
You may need to wait for a while for your CloudFront distribution to take effect if you created both your Amazon S3 and CloudFront bucket just new. Because CloudFront may make a temporary 307 redirect if your S3 bucket was also created recently. In this case please wait without making any changes. After a few hours or so, it should be generally fine.
You can also test this by applying the same steps for an old bucket. You should see that it works.
In this blog post, I tried to explain how you can restrict Amazon S3 bucket access on your Amazon CloudFront distributions. This would make your CloudFront distributions more effective.
Where can you go from here? You can define an
alternate domain and SSL via Amazon Certificate Manager to your CloudFront distribution to access it from a domain like
https://cdn.example.com. Besides, you may further restrict access only through your website using Web Applicaton Firewall (WAF) service. If you serve private content to only subscribed users for a limited time, you can activate signed urls.
Hopefully, I am planning to discuss these topics in this blog in near future.
Thanks for reading!