Secure Your AWS CloudFront Endpoints Before It’s Too Late
Hello guys, in this blog we’re going deep down into one of the well know CDN service build by Amazon i.e., AWS CloudFront. First of all, if you don’t know what AWS CloudFront is or what it does, so let me tell you this in a brief,
“AWS CloudFront is a Global Content Delivery Network service that helps you distribute your static and dynamic content quickly and reliably with high speed and low latency, it is built for service built for high performance, security, and developer convenience. CloudFront speeds up the distribution of your content by routing each user request through the AWS backbone network to the edge location that can best serve your content. Typically, this is a CloudFront edge server that provides the fastest delivery to the viewer.”
Now, you might be thinking, “Securing AWS CloudFront Endpoints? What does that mean? Isn’t CloudFront already secure?”, Well, you’re somewhat right but there’s so much more into AWS CloudFront apart from default settings which will make sure that your CloudFront Endpoint & It’s source origin will be more secure & robust.
For this demo, I’m going to create a S3 bucket which will have some sample html files to host and we will be using S3 feature called, “Static Website Hosting” to use S3 to host out static website & we’ll be accessing the Static site via AWS CloudFront only.
PS: It’s not recommended to use S3 with CDN while Static Website Hosting option enabled since it uses HTTP instead of HTTPS. Just use S3 with Website files & CDN with OAC enabled as suggested by many but since our focus is on CDN security options, let’s continue.
So, for this, we’ll be doing the following steps:
- Creating S3 bucket with custom setting,
- Enabling Static Website Hosting and then uploading sample html files,
- Creating CloudFront Distribution & It’s Perquisites:
• Public certificate using AWS ACM
• Policies:
- Cache
- Origin Request
- Response Headers (IMP!!!) - Testing WAF Options
- Testing Custom Response Headers
I hope these steps are clear otherwise don’t worry, we’ll be going deep into all of these steps and see them in action and try to understand what does these actually do!
So, Let’s begin.
Step 1: Creating S3 bucket with custom settings
To create a S3 bucket first of all we need to go to S3 bucket console by searching in the AWS Console search bar,
Once you’re in, click on Create bucket to create a s3 bucket over AWS cloud,
Now, once inside, all you need is to choose a region in which your AWS s3 bucket & it’s objects will resides and define a globally unique name for your S3 bucket. For e.g.
In next block, we got ACLs option for Object Ownership of bucket objects,
and Block Public Access settings for this bucket, Leave the ACL to disabled.
and for Public access,
Uncheck the Block all public access and tick mark the acknowledgement and move forward.
tbh, there are multiple ways to setup S3 with CDN, I’ve just used one of them, you can get some insights from this link: https://repost.aws/questions/QUIawqJwnLTz2MJNwx7y81kA/cloudfront-access-denied-on-public-s3-bucket
Now, there are some more options like Bucket Versioning, Default encryption & Object Lock which you can choose as per your needs,
I’m leaving all these options to default since it’s fine for my use case.
Once all done, click on Create bucket button at the end of the page and your bucket will be created. Now, let’s move to step 2.
Step 2: Enabling Static Website Hosting and then uploading sample html files
To enable Static website hosting you need to open the S3 bucket, then click on properties and then scroll to the bottom of properties tab there you’ll see Static website hosting option.
By default, the option will be Disabled; you need to click on Edit to modify its settings.
When you click on it, you’ll get options to modify the Static website hosting option,
Click on Enable and you’ll get to choose all the options to setup Static website hosting using S3.
After clicking on Enable, you’ll get following options,
Choose as per your requirements, For Hosting type I’ve kept it to default since the objects will be in same bucket and in the Index document text block you need to mention the Index file name which is index.html in my case.
Error document & Redirection rules are optional but if you need you can modify or change them. Once all set, click on Save changes.
Once this done, you can see in the Properties tab, Static website hosting option is enabled and it will give you a domain something like below,
Now that’s it’s enabled, you need to upload the Index & Error document which is index.html & error.html in my case.
As you can see, I’ve uploaded them into the S3 bucket. Now we need to modify the S3 Bucket policy so that our static files can be accessed from CloudFront distribution only.
To modify this, you need to go to Permissions tab and click on Edit button for Bucket policy.
In the Bucket Policy Editor, you need to write a policy which will allow the objects to be fetched from your anywhere since the CDN will try to access it over the internet.
Here’s an example:
You can check more bucket policy examples from here: https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-restricting-access-to-s3.html
Once done, click on Save changes.
and your S3 objects can be accessible from internet by using Static domain.
As you can see, now it’s showing the website properly, before it was showing Access denied.
Hence our AWS S3 part is done, now let’s move to AWS CloudFront.
Step 3: Creating CloudFront Distribution & It’s Perquisites
Now before going further which means creating AWS CloudFront distribution, we need to create SSL/TLS Certificate using AWS ACM & CloudFront distribution policies.
So, let’s start with AWS ACM:
I’ve already created one Certificate in N. Virginia region since the CloudFront supports ACM in N. Virginia region only.
You can also create one by clicking on Request certificate in ACM console,
Then fill the following details,
And then click on Request. It will give you a CNAME record which you have to enter into domain’s DNS record & you’re done.
Let’s get back to AWS CloudFront console, here we’re going to create custom policies for AWS CDN distribution.
So, Let’s start with creating Cache policy:
When you click on Create cache policy, you’ll get following options,
In Details tab you need to define things like Name & Description, then you can define TTL settings. You can either tweak it as per your need to leave it to default.
Then moving forward, you’ll get following options to modify,
First one is Cache key settings in which you can define the Headers, Query strings and Cookies. You can customize these as per your need. In the Compression support block, you can check or uncheck the options Gzip & Brotil, these totally depends upon the type of data which will be served by AWS CDN. You can check the Managed policies to get some idea about them. Once these done, click on Create and our custom Cache policy is ready.
Now, next is Origin request:
Click on Create origin request policy and you’ll get something similar to below,
In the name & description you can fill whatever you need but for Headers, Query strings & Cookies you should choose only those which you want to forward to the origin. Whatever is enabled, CDN will forward those values in the Origins requests. As of now I’m these setting but this also totally depends upon your use case.
Moving forward to our last policy i.e., Response headers(IMP!!!):
Click on Create response headers policy and you’ll get something similar to below,
And much more…
Now this is the headers policy which will be responsible to respond the headers requests as per custom headers defined here.
First option which we’re going to look is Cross-origin resource sharing (CORS),
This section contains CORS related options which is a mechanism that allows restricted resources on a web page to be accessed from another domain outside the domain from which the first resource was served,
- Access-Control-Allow-Origin = This response header indicates whether the response can be shared with requesting code from the given origin.
- Access-Control-Allow-Origin = This response header indicates whether the response can be shared with requesting code from the given origin.
- Access-Control-Allow-Origin = This response header indicates whether the response can be shared with requesting code from the given origin.
- Access-Control-Allow-Origin = This response header indicates whether the response can be shared with requesting code from the given origin.
- Access-Control-Allow-Origin = This response header indicates whether the response can be shared with requesting code from the given origin.
- Access-Control-Allow-Origin = This response header indicates whether the response can be shared with requesting code from the given origin.
Credentials are cookies, TLS client certificates, or authentication headers containing a username and password. By default, these credentials are not sent in cross-origin requests, and doing so can make a site vulnerable to CSRF attacks.
You can read more about them from here: https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/understanding-response-headers-policies.html?icmpid=docs_cf_help_panel#understanding-response-headers-policies-cors
Next one is Security headers which is a really important policy for CDN & also as security point of view,
This section contains Security related headers options which can be used to secure your CDN endpoints against common malicious requests which can sometimes be issue and also fails security checks so it is good to work on this part as well.
- Strict-Transport-Security = This HTTP response header (often abbreviated as HSTS) informs browsers that the site should only be accessed using HTTPS, and that any future attempts to access it using HTTP should automatically be converted to HTTPS.
- X-Content-Type-Options = The X-Content-Type-Options response HTTP header is a marker used by the server to indicate that the MIME types advertised in the Content-Type headers should be followed and not be changed. The header allows you to avoid MIME type sniffing by saying that the MIME types are deliberately configured.
- X-Frame-Options = This HTTP response header can be used to indicate whether a browser should be allowed to render a page in a <frame>, <iframe>, <embed> or <object>. Sites can use this to avoid click-jacking attacks, by ensuring that their content is not embedded into other sites.
- X-XSS-Protection = This HTTP response header is a feature of Internet Explorer, Chrome and Safari that stops pages from loading when they detect reflected cross-site scripting (XSS) attacks. These protections are largely unnecessary in modern browsers when sites implement a strong Content-Security-Policy that disables the use of inline JavaScript (‘unsafe-inline’).
- Referrer-Policy = This HTTP header controls how much referrer information (sent with the Referrer header) should be included with requests. Aside from the HTTP header, you can set this policy in HTML.
- Content-Security-Policy = This is an added layer of security that helps to detect and mitigate certain types of attacks, including Cross-Site Scripting (XSS) and data injection attacks. These attacks are used for everything from data theft, to site defacement, to malware distribution.
You can read more about them from here: https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/understanding-response-headers-policies.html?icmpid=docs_cf_help_panel#understanding-response-headers-policies-security
Origin override = This setting determines how CloudFront behaves when the response from the origin contains one of the CORS headers specified in this policy
Apart from these, we’ve some more options like,
In Custom headers we can specify additions headers which CloudFront adds to HTTP responses that it sends to viewers.
In Remove headers we can specify headers CloudFront removes from HTTP responses that it sends to viewers.
And the last one is Server-Timing header which communicates with one or more metrics and descriptions for a given request-response cycle. It is used to surface any backend server timing metrics (e.g. database read/write, CPU time, file system access, etc.) in the developer tools in the user’s browser or in the PerformanceServerTiming interface.
Now since our All three Policies i.e., Cache, Origin request & Response headers are ready, we can move forward with creating AWS CloudFront Distribution for our S3 hosted static website.
For this, we need to go to Distributions console and click on Create distributions.
After clicking on this, we’ll get some options like these below,
When you click on the Origin domain it will open a list of AWS services which you can choose among them to server via AWS CloudFront. Here I’ve chosen the S3 bucket which I’ve created earlier for this demo where my Static webpages are hosted.
When you click on it, it will ask you choose the option to use this S3 bucket as Website endpoint, Click on it.
After clicking on it, the below options will change and it will show something similar to below,
In these options, you can’t do much changes except the HTTP (which I don’t suggest to change since our S3 website static endpoint is listening on port 80 only) port & Name. You can choose whatever name you like for the origin.
Moving further, you’ll see following options,
In the first option you can add custom header if you want your CDN to send some custom header requests to origin.
Then there’s option called Enable Origin Shield which will reduce the load on your origin and act as an addition caching layer between CDN and the origin.
Then under Additional settings, you get some options to tweak the options like Connections attempts, Connection timeout, Response timeout and Keep-alive timeout to tweak the origin requests as per your origin behavior.
Next is Default cache behavior where we can define the caching behavior for our CDN endpoint,
Here, in this part you don’t have much to do, just change the Viewer protocol policy to Redirect HTTP to HTTPS traffic and let’s move to next options under cache. In my case there’s nothing much needed to do but in your use case it may differ so please check your origin thoroughly before making changes to these options.
In here, you can choose the Policies which we created previously for Cache policy, Origin request policy and the most important one, Response headers policy.
In additional setting we get following options,
First option is Smooth streaming which is a specific option related to Microsoft IIS, since we’re using S3 as origin, choose Yes here.
The next option is Field-level encryption which is used to encrypt the POST data in transit at edge location.
Then we get option to Enable real-time logs. For this we also need to choose configuration. We can skip this option for now.
Next is Functional associations where we can use CloudFront Functions or Lambda@Edge to do some action on the basis of Viewer requests/response or Origin request/response.
Leaving these options as well since we don’t need these at the moment.
Now moving forward, we have one of the most critical options to enable for CDN i.e., AWS WAF a.k.a. Web Application Firewall which is a dedicated firewall service provided by AWS.
To enable this, all we need to click on Enable security protections and for the initial time, we can enable Use monitor mode so it will just monitor the requests, not block.
I’ve created a separate blog regarding AWS WAF which you can check here:
https://dcgmechanics.medium.com/protect-web-application-with-aws-waf-d6206142ec59
Now, Let’s move to the next options,
Here we’ve options like Price class, Alternate domain name, Custom SSL certificate and Security policy which I don’t think I need to explain since there’s nothing complex about them.
You can choose whatever suits you or fulfills your requirements.
There then are options like Supported HTTP versions, Default root object, Standard logging and IPv6 toggle.
These are options which you can use to enhance the endpoint capabilities like wider protocol support, observability and larger address space to get your API Endpoints working at any condition.
IPv6 feature is also useful in case your origin doesn’t supports IPv6 by default like AWS API Gateway and you still want to connect to your app via IPv6 connection.
Once all these done, click on Create distribution & your Secure AWS CloudFront distribution is ready to serve.
You’ll see something like below once the Distribution is ready to server requests,
Now all we need is to create a CNAME record for your domain which is dcg.codelogicx.com in my case and point it to CDN Domain name which will be provided after creating the distribution.
Once all these done, let’s test the domain from the browser,
As you can see, it’s working fine (tada!).
Same for the Postman,
As you can see the Event & It’s relevant Time are so less which will help to server the users faster with very low latency.
Now let’s move to the testing phase where we’re going to test the options which we implemented while considering left-shift for security.
Step 4: Testing WAF Options
To check WAF Security option, you can go to the distribution’s security tab,
Just to tell you, there are so many things which you can customize in WAF and for this I really recommend you to go through my AWS WAF medium blog whose link I just shared in last step.
We can enable Geographic restrictions, Bot control, AWS WAF logs and many more which will for sure help you monitor and secure your apps which are using AWS CloudFront as endpoint.
Step 5: Testing Custom Response Headers
To test the Custom response headers which we configured in step 3, we’ve so many options, but just for demo purpose I’m going to show how we can test X-Frame-Options which we enabled in Security headers.
For this, I’ll be using W3School’s website iframe IDE. Here we can use our domain to test if we can render the website from different origin or not.
As you can see, the website refused to connect because we’ve set X-Frame-Options header’s origin to SAMEORIGIN so that it can’t be called from some other URLs or domains.
We can also use domsignal.com or other online free/paid services to check the security of our AWS CloudFront endpoints.
I hope you followed till here and clear with all the things which I’ve explained in this blog.
That’s it for now regarding Securing Your AWS CloudFront Endpoints, a really useful AWS service to provide High Availability, Low Latency, Origin Load Offloading, Caching, Security and many more to your application.
If you’ve any queries please ask, I’ll be more than happy to help with your queries.
Till then, Thank you!
remember #SharingIsCaring ;)