I have a CloudFront distribution that serves my React app. (myreactapp.com)
I also have a Lambda Function (an Express app) to receive the POST request that comes from auth service. I want to serve this Lambda Function under the same URL as my CloudFront distribution on /auth endpoint.
So every request that comes to myreactapp.com should serve my React app but if a POST request comes to myreactapp.com/auth, my Lambda function should serve that endpoint.
myreactapp.com is a custom domain added to the CloudFront distribution. I want to use the same domain for the /auth endpoint.
So far, I've tried adding an origin to my CloudFront distribution, selected my Lambda Function as the Origin domain. Then under Behaviors, I added a new behavior, put /auth for the Path pattern, selected my previously created Origin for the Origin/Origin Groups option, and selected GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE for the allowed methods.
I am deploying my Lambda Function with serverless deploy CLI command.
I am new with AWS and couldn't figure this out. I am not even sure if what I am looking for is possible. Could you give me some insights on this?
Related
I am struggeling to get my AWS cloudfront/apigateway setup right. I have a cloudfront with two origins pointing to the same ApiGateway but of different routes. /* as default should be routed to /dev/react and /api/* should be routed to /dev/api/ on the Apigateway. /dev/react is a SSR Lambda rendering a react web page and /dev/api are my API Lambdas. The API Lambdas are protected by the Cognito Authorizer for which I am sending the Authorization header on every request.
This works very well when I serve everything on the ApiGateway domain, no Auth errors or such, but when I try to serve/access it via the cloudfront I can load the react app, via the default behaviour, but when the react app calls the API endpoints I get a IncompleteSignatureException.
I tried forwarding the Host header and other things, but cannot get it to work.
I found this ApiGateway403Erros page where the expl. is A request with an "Authorization" header is sent to an API resource path that doesn't exist., but I can pin point what that means for my scenario?
Is my routing bad? Am i missing an alias domain on the ApiGateway? What makes cloudfront not "finding" the resources on this path?
Any hints would be very much appreciated.
AWS have recently released the Lambda function URLs feature which allows a function to be invoked via a URL.
I would like to allow my function to be invoked via a URL but only via CloudFront.
I don't want people to be able to bypass CloudFront and invoke the function directly.
Is there a way to configure this? I am aware that I can restrict the function URL by setting the auth type to AWS_IAM but am not clear on how I then allow CloudFront to call it.
Currently, the only option I see is quite similar to how you would protect an ALB in a way that access is restricted to CloudFront:
Configure CloudFront to add a custom HTTP header to requests that it sends to the Application Load Balancer lambda function URL.
Configure the Application Load Balancer Lambda to only forward process requests that contain the custom HTTP header.
My thoughts on approaches that may not work when using lambda function URLs:
IAM auth (since I see no way to sign these requests origination from CloudFront, maybe that will change in the future when lambda function URLs become a first class citizen like S3-origins)
restricting access via security groups (because there are no SGs for lambda func URLs)
Confirmed with AWS support that there is currently no way to do this: "[with the] current design of CloudFront, it is not possible for CloudFront to relay IAM authenticated requests to Lambda URL origin.." There is a feature request for this (but they did not provide a timeframe for implementation and release) but hopefully they provide a solution similar to, and as straight forward as, the CloudFront integration with S3 via the Origin Access Identity.
Here's what I did to make it work on my side :
go to the CloudFront page
click on create a new distribution
In section Origin domain you have to paste in your lambda function URL
Make sure to adjust the caching policy depending on what your lambda function consumes
You might want to create a dedicated policy in you want the cache key to depend on the query string, the cookies, etc...
For my use case I created a new policy to take into account the query string
I have an AWS API Gateway API with CORS enabled and a custom domain set-up. Direct API access via the execute-api endpoints is working and I get no CORS issues in the browser. Access via the custom domain api.example.com which I also configured, is working in principle, but not in the browser, where I get CORS:
Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
When setting up the custom domain, API Gateway configures its own CloudFront distribution which is somewhat internal and I do not see how to configure it or if this is even possible, it does not show up in my list of CloudFront distributions, which is expected. From the AWS docs:
The CloudFront distribution created by API Gateway is owned by a
region-specific account affiliated with API Gateway
I found these answers https://stackoverflow.com/a/52435619/4556546 and https://stackoverflow.com/a/51463965/4556546 that describe how to solve the problem with a normal CloudFront distribution. I am, however wondering:
Have I missed something in configuring the custom domain and its
associated CloudFront distribution?
In what circumstances would I choose the custom domain with its internal CloudFront distribution over running my own CloudFront distribution
that I can configure? (I already have a CloudFront distribution that I use for other parts of my app.) Are there pricing implications?
Your suggestion to remove the stage or "/dev" from my new custom domain worked like a charm.
api.example.com/dev/some_endpoint Incorrect
api.example.com/some_endpoint Correct
Hopefully this answer can help anyone else trying to add a custom domaim to AWS API Gateway.
simply removing /dev from the end of my custom domain in my amplify config nailed it! I want to hide under the sheets everytime I see that cors error, in this case I came out on top, thanks!
Using AWS cloudfront with S3 to host an angular-based web client.
Is there any rewrite rule or settings allowing one of the following examples? It is so unclear from what AWS are trying to exaplain.
Using friendly route, for example:
domain.com?lang=en&fun=no => domain.com/en/no
Configuration folders to have a default file, for example:
domain.com\en => domain.com (but now the client knows it has a parameter lang=en)
Obviously both of the example can be done with an html file which routes to the desired url BUT it doesn't work well with some sort of analytics models such as google's.
I would suggest using 'AWS Lamda at the Edge' functionality to provide the custom rewriting you want:
Using CloudFront with Lambda#Edge
Lambda#Edge is an extension of AWS Lambda, a compute service that lets you execute functions that customize the content that CloudFront delivers. Lambda#Edge scales automatically, from a few requests per day
to thousands per second. Processing requests at AWS locations closer
to the viewer instead of on origin servers significantly reduces
latency and improves the user experience.
When you associate a CloudFront distribution with a Lambda#Edge
function, CloudFront intercepts requests and responses at CloudFront
edge locations. You can execute Lambda functions when the following
CloudFront events occur:
When CloudFront receives a request from a viewer (viewer request)
Before CloudFront forwards a request to the origin (origin request)
When CloudFront receives a response from the origin (origin response)
Before CloudFront returns the response to the viewer (viewer response)
and here is an aCloudGuru blog post with lots of good examples, including one specifically about url rewriting:
https://read.acloud.guru/supercharging-a-static-site-with-lambda-edge-da5a1314238b
In a multipage web app (say 12 pages), you will want to use an automated and worry-less strategy via AWS Lamda#Edge. It solves this completely.
First, create an AWS Lambda function and then attach your CloudFront as a trigger.
In the code section of this AWS Lamda page, add the snippet in the repository below.
https://github.com/CloudUnder/lambda-edge-nice-urls/blob/master/lambdaRewrite.js
Content delivery will still be as fast as you can blink your eyes.
PS: Note the options in the readme section of the repo above
I have a website distributed with CloudFront, with S3 as an origin. I've written a Lambda function that takes a contact form submission and sends the email along with SES. The Lambda test out just fine : )
But, I'm clueless when it comes to routing POST requests from CloudFront to that backend Lambda function. How do I do this?
Update: Okay, I've got the API Gateway test triggering the Lambda function just fine, but I can't seem to call it from CloudFront (or rather using a curl command to my domain set up with CloudFront).
Do I need to list my domain as a custom domain in API Gateway?
If I list the path /api/* in my CloudFront Behaviors, do I have to mirror that in my API Gateway set up? So, does my API Gateway need to start with /api before I add specific resources?
Update 2 I think I needed to leave or remove the /dev off the end of the API Gateway URL. dev being my stage.
Update 3 Okay, it feels one step away now. I've got everything hooked up. The test request hits cloudfront, it forwards to api gateway, gateway calls lambda (at this point I'm shaking my head at how complicated we've made all this), and lambda sends back success or failure to api gateway, and we're peachy. Except, I get MethodNotAllowed when I do it from curl or the browser. Do I need to add an IAM role to CloudFront to access API Gateway?
Update 4 Still not working. And now, I'm back to getting my usual 404 error page that my Default Origin (S3). Seems like serverless is a fading dream.
Update 5 Trying a different approach, recommended here: https://serverfault.com/a/839368 The idea is to use API Gateway's Custom Domain name features with a subdomain like api.example.com and then use a Route53 Alias record to direct subdomain traffic to API Gateway. This could work. Then CloudFront would handle traffic to example.com and www.example.com, and API Gateway would get requests to api.example.com. Now the challenging bit is that in HTML forms the action attribute will have to go to a different subdomain. Let's see what kinds of errors and crazy behavior we get : (
First you would setup API Gateway in front of your Lambda function so it can be called via a POST request. It sounds like you may already have that part done?
Then if you want the POST to go through CloudFront you would add a second origin in CloudFront that points to your API Gateway.
This is all possible, but its tricky to configure. To help I created an open-source boilerplate app that correctly sets up:
A static site with CloudFront and S3
An API with API Gateway and Lambda
CORS between the static site and API
Optional OAuth 2.0 and JWT cookie for the static site
See this static JavaScript app for an example of a static site POSTing to an API backed by Lambda.
Depends on what you're using as your backend (which language, framework, etc.), there are different ways, but 'em all about one thing: Invoke
Kind-of the most generic call - HTTP is right there, the API call examples by language are referenced at the end of the doc.