Serve single page app under specific path with AWS - django

At the moment I have mydomain.com pointing to a Django EC2 instance with ABL in front of it and CF in front of the ABL.
Now I have the requirement of serving a React single page app under an specific path mydomain.com/my-specific-path (of course everything under HTTPS)
I tried everything I could to host my SPA in an S3 bucket and use CF to redirect the calls to that S3. But it was impossible to serve the app over HTTPS that way (because of S3 hosting and subfolders).
I am thinking now about setting a reverse proxy in front of my Django app. But I don't know if that is the best solution, and I don't know the best way to do it.
Could you please give me some insights about how to serve a SPA under a specific path?
Thank you in advance.

You need to:
1) Add your ALB as an origin to your CloudFront distribution
2) Add your S3 bucket website URL as an origin to your CloudFront distribution
Note: Adding S3 as an origin from the dropdown box that auto populates here will not work for hosting a website out of S3. This feature is for hosting static files only.
2a) Optionally lock your S3 bucket down to CloudFront using a condition in the bucket policy that checks for header value that only CloudFront and your S3 bucket knows
3) Set the default root object in your CloudFront distribution to be index.html
4) Upload your react app to a sub-folder in your S3 bucket, not in the root. This sub-folder must match the path you set on your React app origin in CloudFront
5) Set a default behaviour in your CloudFront distribution that points to your ALB
6) Set a behaviour in your CloudFront distribution that points my-specific-path/* to your S3 bucket origin
7) Terminate SSL on your CloudFront distribution using AWS Certificate Manager
This setup should give you SSL on both your Django app and your React app being hosted in S3.
I've got this running, screen shots below:

Related

Protect webfonts via Amazon CloudFront from download

Is it possible to protect data embedded on my website via Amazon CloudFront from hotlinking or other downloads? I am mainly interested in protecting webfonts from being downloaded.
Amazon CloudFront is connected to a S3 Bucket
S3 Bucket Policy controls allowed domains for files via CloudFront
You think that could work?
Since you have cloudfront setup connected to your s3 bucket, you can use Cloudfront Signed Urls to prevent download by anyone from the public.
You can put your fonts in a folder called fonts for example, and setup a separate behaviour in cloudfront for any path that contains /fonts/ and in there you can activate Restrict Viewer Access.
In your website, you will need to add some way to generate the presigned url for this only when your webpage is loaded and you can put a short expiry time for this URL.

What is the best way to point domain to a S3 bucket that doesnt have the domain as bucket name

I'm new to AWS and all of it's services and my first go at it I started my project with a S3 bucket that was created by default by AWS Vue CLI. I've got Cognito pool & gateway API connected to this bucket but now that I want to connect this project to a custom domain I just purchased I realize the bucket name needs to match the root domain name. From what I understand this will mean that I need to pull all non-aws files from my Vue project, duplicate it, and either reconfigure pre-existing connections or start all over.
I've got my custom domain set up with an empty S3 bucket, Cloudfront, and Router 53 so that's up and working but now I am not sure how to go about transferring this project from buckets.
So basically I started my project with Bucket1 and finished everything that included Cognito Pool & Gateway API. Now I have a custom domain I want to use have Cloudfront and Route 53 with CustomDomain bucket name and I want to have the project from Bucket1 load for the new bucket.
Using Cloud-front you can mitigate this issue.
Route 53(DNS Name) --> Cloudfront Url --> S3 origin
As you already created a bucket for website hosting, below steps can help you.
Use the Amazon S3 console t to login and search for CloudFront.
Click on Create distribution
Create a Web distribution
Select existing bucket in Origin Domain Name and complete the setup.
Update the DNS records for your domain to point your website's CNAME to your CloudFront distribution's domain name. You can find your distribution's domain name in the CloudFront console in a format that is similar to d1234abcd.cloudfront.net.
Wait for your DNS changes to propagate and for the previous DNS entries to expire.
The typical AWS way to do this is to use cloudfront - the domain points to cloudfront and cloudfront can point to any bucket name or other source location; when you introduce cloudfront into the mix, the bucketname no longer needs to match the domain name.

AWS S3 sending download.txt file

I'm setting up an S3 bucket behind CloudFront that is meant to serve static assets. My problem is doing a / on any directory with no file name will have the browser download a download.txt with 0 bytes. I have my S3 bucket setup for Static Website Hosting and is pubic, so I'm able to access my assets.
https://s3-bucket.domain.com/path/to/file.jpg -> get asset, working
https://s3-bucket.domain.com/path/to/file-bad-name -> Error status 403, working. Renders error.html from S3.
https://s3-bucket.domain.com/path/to/ -> sends download.txt, not working
How do I configure #3 to not send a download.txt and render an error page instead?
There are few things happening there.
You need to map it to new origin if you want to point the path to an S3 object.
Your pattern is not having priority in CloudFront.
If you fix one of the above or both, then it should work as expected.
I have my S3 bucket setup for Static Website Hosting and is pubic
...but you selected the bucket from the dropdown list when defining the origin... yes?
You need to configure the origin domain name to use the web site hosting endpoint for the bucket.
When you configure your CloudFront distribution, for the origin, enter the Amazon S3 static website hosting endpoint for your bucket. This value appears in the Amazon S3 console, on the Properties page under Static Website Hosting. For example: http://bucket-name.s3-website-us-west-2.amazonaws.com
https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/DownloadDistS3AndCustomOrigins.html#concept_S3Origin_website
If you don't do this, and you created folders in the bucket using the S3 console, then what you are currently observing is the expected behavior, a side effect of the way the console creates those imaginary folders.

How to serve static web content from S3 backed by multiple buckets from different regions

I'm trying to serve static web content (HTML, CSS, and JS files) from S3 buckets. I know I can go to the bucket's properties tab and choose the item Use this bucket to host a website from the Static website hosting box. And I'm sure this step will still be part of the solution I'm looking for but it won't be all.
Here's what I'm trying to accomplish:
Deploying the same content to multiple regions and based on availability and/or latency, provide the service to the client.
As for the API Gateway, I know how to do this. I should create the same API Gateway (alongside underlying lambda functions) and Custom Domain Names in all the regions. And then creating the same domain on Route 53 (of type CNAME) and choose Latency as Routing Policy. One can also set up a Health Check for the Record Set so availability of the API Gateway and lambda functions are checked periodically.
Now I want to do the same for the S3 bucket and my static content. i.e. I want to deploy the same content to different regions and somehow make Route 53 to route the request to the closest available bucket. Previously, I was using CloudFront but it seems to me in this setup, I can only introduce one bucket.
Does anyone know how can I serve my static content from multiple buckets? If you are going to suggest CouldFront, please tell me how you plan to use multiple buckets.
You can generate a certificate, setup a CloudFront distribution to grab the content from your bucket and then point your domain to your distribution using Route53. You get free https and you can also add several S3 buckets as origins for your distribution.
From AWS Docs:
After you configure CloudFront to deliver your content, here's what happens when users request your objects:
1. A user accesses your website or application and requests one or more objects, such as an image file and an HTML file.
2. DNS routes the request to the CloudFront edge location that can best serve the request—typically the nearest CloudFront edge location in terms of latency—and routes the request to that edge location.
3. In the edge location, CloudFront checks its cache for the requested files. If the files are in the cache, CloudFront returns them to the user. If the files are not in the cache, it does the following:
3a. CloudFront compares the request with the specifications in your distribution and forwards the request for the files to the applicable origin server for the corresponding file type—for example, to your Amazon S3 bucket for image files and to your HTTP server for the HTML files.
3b. The origin servers send the files back to the CloudFront edge location.
3c. As soon as the first byte arrives from the origin, CloudFront begins to forward the files to the user. CloudFront also adds the files to the cache in the edge location for the next time someone requests those files.
P.D. Keep in mind this is for static content only!
This is possible with CloudFront using Lambda#Edge to change origin based on answer from Route 53.
Please refer this blog for a sample Lambda#Edge code to do this -
https://aws.amazon.com/blogs/apn/using-amazon-cloudfront-with-multi-region-amazon-s3-origins/

Calling cross domain requests from almost static site

I'm using vuejs and almost everything I do is on client-side, but for thing I need to call the server-side to check if URL exists or not.
I don't want to make these requests from browser, because that doesn't make sense to fetch different website from my scripts that will be more like calling any bad website without user knowing it in background, so I need to call cloud-function(gce) or aws lambda(since I don't want to host the site on server for it, since it has just one api call).
What would be the best way to accomplish it, I'm looking for something like website is www.webapp.com and cloud-function call on www.webapp.com/checkUrl
If you choose AWS platform, you can use S3, CloudFront, Route53, API Gateway and Lambda to accomplish your goal.
Step01
Create a S3 bucket and upload your frontend vueJs code
Enable Static Web Hosting onto your bucket from S3 properties
Create a CloudFront distribution
Create a CloudFront origin pointing to your s3 bucket url (you have to add static website url of the s3 bucket)
Set the default behaviour pointing to S3 orgin ID
Step 02
Create your lambda function
Create a API gateway
Add new resource (GET/POST) pointing to your lambda
Deploy your API
Go back to the CloudFront distribution and add a origin pointing to your API Gateway
In the behaviour tab, create a new behaviour eg: (/checkUrl) and point it to the OriginId of the API Gateway
Step 03
Goto Route53 and create a new Hosted Zone
Set the NS records of the hosted zone in your domain configuration
Create a new record set (eg: www.webapp.com) and point it to the DNS of your CloudFront distribution
Update your CloudFront distribution's Alternate Domain Name to www.webapp.com