Routing to REST API on ElasticBeanstalk through CloudFront - amazon-web-services

We have this setup where
Express API running on Elastic Beanstalk environment behind an ALB.
S3 bucket for static content.
CloudFront as an access point for everything.
For some reason, CloudFront simply refuses to return a response from the API.
PathPatterns are configured like this:
where APIOrigin is pointing to the the ALB in front of the Beanstalk environment.
The only thing the I'm getting from the endpoint xxxx.cloudfront.net/api/health is this:
Sorry, cannot embed images yet
Yet calling the addess {loadbalancerUrl}/health returns the correct response.
The xxx.cloudfront/api response contains headers
Access-Control-Allow-Origin
Access-Control-Allow-Headers
Access-Control-Allow-Methods
exactly like the Express API on Beanstalk sets them, so some communication exists there, but no response. (JSON response is expected)
We are avoiding using API Gateway for company reasons.
What can I try next?

Related

Post request with form-data via CloudFront

I have a ec2 server and it's using CloudFront because it needs to use https with cerificate signed by AWS. And then there is some API inside this ec2 server that i need to use post method with form-data. but the server somehow can't get the form-data. Is there some cache policy that i have to set? or CloudFront is purposedly forcing me to do everything with the API gateway thing?
Your setup that uses Cloudfront to terminate TLS and forward HTTP requests to EC2 is fine.
You can try turning on forwarding all Query strings and see if it works for you

Can I get an example of how to connect a lambda function to a domain name?

I've been wasting about 12 hours going in circles in what seems like this:
I am trying to just make a simple static landing page in lambda and hook the root of a domain to it.
The landing page works, but api gateway didn't because AWS doesn't seem to set permissions properly by default ("internal server error" with API gateway and lambda on AWS) but now the gateway link works.
So the next steps were the following:
add a custom domain name in the api gateway
add the api mapping in the custom domain name
in route 53, create a wildcard certificate with *.domain.com and domain.com
create an A record that points to the api gateway with domain.com
create a CNAME record that points to the A record
and I get an error 403 with absolutely nothing in the log. I log both 'default' and '$default' stages in the api gateway.
I read https://aws.amazon.com/premiumsupport/knowledge-center/api-gateway-403-error-lambda-authorizer/ which is all about looking at what's in the logs...
and I find the doc is both everywhere and nowhere because it's built as chunks of 'do this' and 'do that' without ever painting a whole picture of how each piece is connected to the other, or any graph with the hierarchy of services, etc. Reminds me of code that works only when you follow the example documented and breaks otherwise.
I'm sure I'm doing something wrong, but given the lack of logs and lack of cohesive documentation, I have no idea about the problem.
Not to mention that http doesn't even connect, just https.
Can anyone outline the steps needed to achieve this? essentially: [http|https]://(www).domain.com -> one lambda function
You cannot use API Gateway for an HTTP request; it only supports HTTPS.
From the Amazon API Gateway FAQs (emphasis mine):
Q: Can I create HTTPS endpoints?
Yes, all of the APIs created with Amazon API Gateway expose HTTPS endpoints only. Amazon API Gateway does not support unencrypted (HTTP) endpoints. By default, Amazon API Gateway assigns an internal domain to the API that automatically uses the Amazon API Gateway certificate. When configuring your APIs to run under a custom domain name, you can provide your own certificate for the domain.
You can use CloudFront to automatically redirect HTTP to HTTPS. How do I set up API Gateway with my own CloudFront distribution? provides a pretty simple walkthrough of connecting an API Gateway to CloudFront (you can skip the API Gateway portion and use the one you created). The important thing you'll need to do that is not in that document is to select Redirect HTTP to HTTPS.
If you truly need HTTP traffic you're probably going to need to go with an ALB.

Plumbing for API Gateway to Beanstalk with SSL

I am looking to host an API which I can control customer access to using API Keys, Usage Plans, and Cognito. This is my first time trying to bootstrap DNS+SSL and I can't figure out the basic plumbing to get SSL working when I connect API gateway to my beanstalk environment.
I've got example.com purchased on namecheap. I've got namecheap DNS set up to forward the api subdomain to AWS DNS via an NS record. I've got an API gateway with a custom domain name of api.example.com mapped to an API with a production stage. I've then got route 53 set up to point api.example.com to that API gateway stage. I can curl api.example.com and because I have a cognito user pool authenticator, I see Unauthorized as the response.
What I'm stuck on is how to connect this to my elastic beanstalk environment. My current attempt involves turning the API Gateway into a "HTTP Proxy", and tweaking the endpoint url. Except I'm not sure what to put there, or how to configure what I put there because the Test button in API GW often throws an error.
I'm currently trying to use the domain name of the load balancer in front of beanstalk: https://load-balancer-in-front-of-beanstalk-endpoint.com/{proxy}. I've tried a few configs on that load balancer, but I'm not sure what cert to give it because when I try api.example.com,
it fails with "Host name dualstack.awseb.foo.elb.amazonaws.com does not match the cert provided by peer(api.example.com)".
Some other questions mentioned setting an alias for api.example.com to point to the load balancer's ip... except for me it already points to the API GW, so I think I've gone wrong somewhere. Could use some pointers.

How can I put rout53 infront of appsync endpoint without cloudfront?

I am building a graphql server using AWS appsync. It generates a random endpoint URL and I'd like to put it behind a DNS customer domain. I have read this article https://aws.amazon.com/blogs/mobile/use-a-custom-domain-with-aws-appsync-amazon-cloudfront-and-amazon-route-53/ and it mentions cloudfront. I don't really need any cache for my application so I wonder why do I need cloudfront?
Can route53 forward the request to appsync endpoint? I don't understand why I need cloudfront. I thought route53 can work as a proxy to forward request from customised domain to target domain.
There is an open GitHub issue for this feature:
Feature Request: Custom domain name
Based on the issue, the use of CloudFront as in your link, seems to be the only feasible way for now to have custom domains with SSL certificates for your appsync endpoint. Using API Gateway to proxy requests to your endpoint also seems as a possibility.

Is it possible to use Amazon Web Application Firewall with application that not hosted on AWS instances?

I'm new with AWS WAF and get stuck with setting up it for application that hosts on some dedicated server. I didn't find any information how to set up it without migration to aws servers, but I found that WAF integrated with CloudFront. But anyway I found only few information that explain how to integrate this CDN with my web application. So, the main question is:
Is it possible to use AWS WAF with application that hosted on some dedicated server? And if it possible - can you provide some guides and/or docs for setting up?
Yes, you can use WAF with a server outside AWS.
WAF works with CloudFront, and CloudFront does not require the origin server to be in the AWS ecosystem.
When you create a distribution, you specify where CloudFront sends requests for the files. CloudFront supports using several AWS resources as origins. For example, you can specify an Amazon S3 bucket or a MediaStore container, a MediaPackage channel, or a custom origin, such as an Amazon EC2 instance or your own HTTP web server. (emphasis added)
https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/DownloadDistS3AndCustomOrigins.html
Configuring CloudFront to work with your external server is no different than configuring it to work with a server in EC2. Your DNS entry (e.g. www.example.com) changes to point to CloudFront, and CloudFront connects to your server using a new name that you create (e.g. origin.example.com). CloudFront proxies requests through to your server, unless the edge location handling the a given request happens to have access to a copy of the same resource that it cached while handling a previous request for the same page -- that's how CloudFront gets your content, by caching it as it handles requests that are passing through. (You don't pre-load any content into CloudFront.) If CloudFront has a cached copy, your server sees nothing, and CloudFront returns the object to the browser from its cache. But CloudFront isn't strictly a CDN, even though they market it that way. It is a global network of reverse proxies and high-reliability/low-latency transport.
You'll want to take steps to ensure that the web server rejected requests that didn't come through CloudFront. See Using Custom Headers to Restrict Access to Your Content on a Custom Origin as well as the list of CloudFront IP Addresses which you could use on your web server's firewall.
Once you have your site working through CloudFront, all you do is activate WAF on the distribution. CloudFront is very tightly integrated with WAF so that is a very simple change, once you have your WAF rules set up.