AWS: How to configure Cloudfront for Custom Domain Names - amazon-web-services

My setup:
API Gateway - 10 APIs (api1, api2,...), all mapped to one custom domain name (api.xxx.com)
Route53 - api.xxx.com pointed to my Cloudfront distribution
Cloudfront - distribution created, api.xxx.com set as a CNAME
What I need to know - I would like to set Origin of this Cloudfront to this custom domain name, so I can call APIs like api.xxx.com/api1/endpoint, api.xxx.com/api2/endpoint. But how? I used API Gateway Name of my api.xxx.com Custom Domain name (xxxxxxx.execute-api.us-east-1.amazonaws.com) for default behavior Origin name and assumed that requests to all 10 APIs will be routed correctly, but it´s not happening,
What works: I created Origin name using the Invoke Url of api1 and assigned it to the Default behavior. So now, when I call "https://api.xxx.com/endpoint", api1 gets called. That makes sense, but the problem is - I need the path to the API to be the part of the URL, such as "https://api.xxx.com/api1/endpoint" so I can differentiate between them.
What doesn't work: But I need several APIs set in the distribution so I can call them like "https://api.xxx.com/api1/endpoint" and so on. And if I use Invoke URL as the Origin name for the API, I cannot attach this API name also to the URL, that returns 403. I was hoping that if I used "API Gateway domain name" of "Custom Domain Names" (after all, it has a format of xxxxx.execute-api.us-east-1.amazonaws.com), I could then use APIs in the URL, but that doesn't work. I cannot even use this "API Gateway domain name" to call individual apis through Postman. Could someone advise me on how to do it? How can I configure Cloudfront so it can call various APIs and use their routes in URL?

Finally found a solution, described in more detail in this discussion thread. My problem was that I was trying to use link to custom domain name (xxxxxxxxxxxx.execute-api.us-east-1.amazonaws.com) directly from Cloudfront, but I should have used "nice", readable address as Origin name and do the redirect in Route53
Working setup:
In API Gateway, Custom Domain Name regional-api.xxx.com is created, endpoint type Regional (xxxxxxxxxxxx.execute-api.us-east-1.amazonaws.com).
In Route53, A and AAAA records map regional-api.xxx.com to the Regional endpoint target domain name.
Cloudfront distribution created that uses regional-api.xxx.com as the Origin Domain Name and api.xxx.com as a CNAME.
In Route53, A and AAAA records map api.xxx.com to the Domain name of a newly created CF distribution.

My setup is a bit different then yours but it seems we want to accomplish the same goal.
I have four S3 buckets which I serve through cloudfront.
One bucket is the root website; 3 other buckets contain 3 different admin panels
For each s3 bucket I created an seperate origin; I believe you should create an origin for each seperate api.
I added for each origin group two path patterns; I believe for your api you can have one pattern per api. A path pattern could look like /api1/* which points to the origin of api1
Not sure if you tried adding origins for all your api's.

Related

Unable to configure the Route53 to point to CloudFront Distribution for the static website hosted on S3

I am trying to deploy my static website to S3 configuring CloudFront in front of it. But I am not able to configure Route53 to integrate with CloudFront. Below is what I have done so far.
I create an S3 bucket enabling static hosting and allowing public access. Then I deployed/ uploaded the files. I can access my website through the S3 website static URL, http://www.waiyanhein.com.s3-website-eu-west-1.amazonaws.com/.
I have my own domain called, waiyanhein.com.
I am trying to configure the CloudFront in front of my static website. So I created a CloudFront distribution. For the Origin Domain Name, I chose the S3 Bucket's static website URL. Then I chose "Compress Objects Automatically" as YES. In the "Alternate Domain Names (CNAMEs)" text field, I entered, "waiyanhein.com". Then I created the CloudFront distribution. Now my CloudFront distribution is up and running.
Then I tried to configure Route53 pointing to the CloudFront distribution. I tried creating a record choosing "Alias to CloudFront distribution" option. But I can't find my CloudFront distribution in the resources as you can see in the screenshot below.
What's wrong with my configuration?
I have sort of found out something in the CloudFront distribution too. When I edit the CloudFront distribution, the Alternative domains field is empty for some reasons. Then I entered the domains and clicked save. Then I got the following error.
com.amazonaws.services.cloudfront.model.InvalidViewerCertificateException: To add an alternate domain name (CNAME) to a CloudFront distribution, you must attach a trusted certificate that validates your authorization to use the domain name. For more details, see: https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/CNAMEs.html#alternate-domain-names-requirements (Service: AmazonCloudFront; Status Code: 400; Error Code: InvalidViewerCertificate; Request ID: 2d1bacd5-794c-46e5-beec-70b24fab83a6; Proxy: null)
If it does not appear automatically in the dropdown then AWS would be filtering this as it believes that the exact domain you intend to use is not usable for any CloudFront distributions in the account.
Please check the following are correct:
The exact record is covered by the alternative name(s) attached to the CloudFront distribution.
The CloudFront distribution is finished rolling out.
From the interface for the Alias value you should be able to paste the CloudFront domain name with a trailing . although in this new interface certain actions do not currently appear to work. If this is the case for you revert back to the original interface by clicking on the Switch to old console link on the left hand side of the screen and attempt from here.
Additional Comments
The screenshot indicates that an alternative domain that is being specified does not have a matching ACM certificate in us-east-1 which is attached to your CloudFront distribution.
If you do not have one generate a new one, then attach it to your CloudFront distribution when you add the alternative domain name.

How to prevent direct access to cloudfront domain name and instead only via custom domain

I've set up a static site on AWS with route 53, ACM, cloudfront and s3. However although I can prevent direct access to the bucket's generated domain name via a bucket policy so that access is only via my custom domain eg www.example.com I'm not sure how to do this for cloudfront and currently the website can be accessed via a cloudfront domain name eg 23324sdfff.cloudfront.net
Is there a way to prevent access to the website via the cloudfront domain name so that traffic can only access the site directly via www.example.com?
I think you could achieve that using Lambda#Edge.
Specifically you could create a function for viewer-request. The function would inspect the request and then decide if to allow or deny it.
Sadly, I don't have concrete example addressing your specific use-case. But AWS docs provide a number of examples that could be useful to you.
Maybe,there is an easier way not involving the lambda, but at present I'm not aware of such a possibility.

AWS unable to enforce https for S3 bucket

I have tried several tutorials on how to set up https via CloudFront, but nothing is working. I am hosting from an S3 bucket and the app works fine via the http protocol, but I need it to be https.
Does anyone have a very thorough tutorial on how to make this work?
Some tutorials explain how to go about setting up a certificate, some explain how to use CloudFront to handle its distribution and I even found a CloudFront tutorial that explains how not using a link from the CloudFront setup forces the wrong region to be created for a certificate, so I even tried that.
I have not found anything that explains exactly what needs to be done for this very common setup, so I am hoping that someone here has some helpful resources.
I think the main issue I had when setting up a CloudFront distribution for an S3 static webhosting bucket was in the Orign Domain Name.
When you create a new distribution, under Origin Settings, the Origin Domain Name field works as a drop-down menu and lists your buckets. Except that picking a bucket from that list doesn't work for static webhosting. You need to specifically put the endpoint for the bucket there, for example:
mywebhostingbucket.com.s3-website-sa-east-1.amazonaws.com
And for custom domains, you must set up the CNAMEs under Distribution Settings, Alternate Domain Names (CNAMEs), and then make sure you have your custom SSL certificate in the us-east-1 region.
Then you can configure the alias record set for the CloudFront distribution.
Here is a complete answer for setting up a site with https.
I had everything in this document completed:
https://docs.aws.amazon.com/AmazonS3/latest/dev/website-hosting-custom-domain-walkthrough.html
And it worked to get the site live via http, but in order to add https, I needed to do the following:
I had requested a certificate for whatever.com, and tried several suggestions after that. But there were a couple of things missing.
To route traffic for the domain (whatever.com) to CloudFront distribution, you will need to clear the current value of the A record and fill in distribution domain name.
Several documents that I viewed said to point the whatever.com S3 bucket to the www.whatever.com S3 bucket, and use the second one to drive the site. Since CloudFront can serve multiple domain name, you may set CNAME of distribution with both, but you will need to set A record for both to distribution AND request an ACM certificate with both domain names (with and without the www). Also, I did ask this, so if you already have a certificate, you can't edit it to do this, which means you'll need to request a new one that has both whatever.com and www.whatever.com
After all of this, I still got "Access Denied" when I went to my site, so to fix this issue, I had to create a new origin in CloudFront with 'Origin Domain Name' set to the full address of the S3 bucket (without the http), and then set the Default (*) Behavior to the S3-Website-.....whatever.com bucket.
After all of this, my site was accessible via http AND https. I hope this helps anyone who experienced this challenge.

Cloud Front - overlapping Alternate Domain Names

In Api Gateway I've created one custom domain, foo.example.com, which creates a Cloud Front distribution with that CNAME.
I also want to create a wildcard domain, *.example.com, but when attempting to create it, CloudFront throws an error:
CNAMEAlreadyExistsException: One or more of the CNAMEs you provided
are already associated with a different resource
AWS in its docs states that:
However, you can add a wildcard alternate domain name, such as
*.example.com, that includes (that overlaps with) a non-wildcard alternate domain name, such as www.example.com. Overlapping domain
names can be in the same distribution or in separate distributions as
long as both distributions were created by using the same AWS account.
https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/CNAMEs.html#alternate-domain-names-wildcard
So I might have misunderstood this, is it possible to accomplish what I've described?
This is very likely to be a side-effect of your API Gateway endpoint being configured as Edge Optimized instead of Regional, because with an edge-optimized API, there is a hidden CloudFront distribution provisioned automatically... however, the CloudFront distribution associated with your API is not owned by your account, but rather by an account associated with API Gateway.
Edge-optimized APIs are endpoints that are accessed through a CloudFront distribution that is created and managed by API Gateway.
— Amazon API Gateway Supports Regional API Endpoints
This creates a conflict that prevents the wildcard distribution from being created.
Subdomains that mask a wildcard are not allowed to cross AWS account boundaries, because this would potentially allow traffic for a wildcard distribution's matching domains to be hijacked by creating a more specific alternate domain name -- but, as you noted from the documentation, you can do within your own account.
Redeploying your API as Regional instead of Edge Optimized is the likely solution. If you still want the edge optimization behavior, you can create another CloudFront distribution with that specific subdomain for use with the API. This would be allowed, because you would own the distribution. Regional APIs are still globally accessible.
Yes it is. But keep in mind that CNAMEs set for CloudFront distributions are validated to be globally unique, including API Gateway distributions. So this means you (or any other account) have that CNAME already set up. Currently there is no way to lookup where the conflict is, you may need to raise a ticket with AWS support if you can't find that yourself.

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