Secure Your AWS CloudFront Endpoints Before It’s Too Late

Devashish Gupta
codelogicx
Published in
16 min readJan 19, 2024
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:

  1. Creating S3 bucket with custom setting,
  2. Enabling Static Website Hosting and then uploading sample html files,
  3. Creating CloudFront Distribution & It’s Perquisites:
    • Public certificate using AWS ACM
    • Policies:
    - Cache
    - Origin Request
    - Response Headers (IMP!!!)
  4. Testing WAF Options
  5. 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,

Choose S3 from AWS Console

Once you’re in, click on Create bucket to create a s3 bucket over AWS cloud,

Create S3 bucket

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.

Bucket configurations

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.

Object Ownership

and for Public access,

Block Public Access settings for this bucket

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,

Bucket versioning and Default encryption
Object Lock

I’m leaving all these options to default since it’s fine for my use case.

Create bucket with custom configurations

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.

Bucket Properties
S3 Static website hosting Disabled

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,

Static website hosting enable options

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,

Edit static website hosting

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,

Static website hosting comain

Now that’s it’s enabled, you need to upload the Index & Error document which is index.html & error.html in my case.

HTML files uploaded in S3 bucket

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.

Edit 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:

Bucket Policy for GetObject Public access

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.

Successfully edited bucket policy

and your S3 objects can be accessible from internet by using Static domain.

dcg static website hosted via s3 statis website hosting

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.

ACM Certificate

You can also create one by clicking on Request certificate in ACM console,

ACM Request certificate

Then fill the following details,

Request public certificate

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.

CloudFront Policies

So, Let’s start with creating Cache policy:
When you click on Create cache policy, you’ll get following options,

Create cache policy

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,

Cache key settings & Compression support

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,

Create origin request policy

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,

Create response headers policy

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),

Cross-origin resource sharing

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,

Security headers

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,

Custom headers, Remove headers & Server-Timing header

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.

Create discribution console

After clicking on this, we’ll get some options like these below,

Choose Origin domain

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,

Distribution options

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,

Add custom header, Enable Origin Shield & Additional settings

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,

Default cache behaviour

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.

Cache key and origin requests

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,

Smooth streaming & Enable real-time logs

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.

Functional associations

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.

Web Application Firewall (WAF)

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,

Price class, Altername domain name & custom SSL certificate

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.

Supported HTTP versions, Default root object, Standard logging & 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,

CloudFront Distribution

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,

dcg.codelogicx.com working fine

As you can see, it’s working fine (tada!).
Same for the Postman,

Postman call response

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,

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

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.

W3school iframe test IDE

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.

domsignal HSTS test

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 ;)

--

--