AWS API Gateway proxy with AWS Lambda as middle ware - amazon-web-services

I would like to use you AWS API Gateway as a single entry point to my backend which will proxy (redirect) request to different microservices based on URL prefix. However before to do proxy it would be nice to have lambda which may check requests and make a decision if allowed to make proxy or it's better to make a response imidiatly, so, in another word, I would like to have AWS lambda as middleware. Is it possible to do?

Short answer
Yes, but don't do it. There are other solutions.
Explanation why you shouldn't do it
You can use a lambda in between your containers and API gw but using a lambda as a 'middleware' is an antipattern, you will have to pay double by making your lambda wait on your microservices response.
Other solutions
If you want to handle authentication or check headers and cookies you should use a lambda authorizer.
For your use-case you can make use of an application loadbalancer. That can do path redirects to different target groups.
https://aws.amazon.com/premiumsupport/knowledge-center/elb-achieve-path-based-routing-alb/
It might make sense in having a library that is shared by the different microservices that does the early response or request checking.
Not sure what is your real goal and use case but if you elaborate more on what you'd like to achieve, I might can help.

IMHO this would be the job of API Gateway - based on different URIs & HTTP Methods you may forward the request to different lambdas. You can also check /validate your request params/body and/or add Authorizers (including a Lambda).
It would be interesting to know more about the use case and if the API GAteway would be suitable for it

Related

Calling lambda from another lambda or exposing api through api-gateway

I am contemplating if I should invoke lambda directly from another lambda or should I expose api through api-gateway in front of lambda. I am looking for pros and cons for both.
Approach #1 Using API Gateway
API Gateway and Lambda have one of the best integrations for serverless applications. It is very widely used and offers a ton of features - proxy integration, mapping templates, custom domain names and different types of authentication.
However, with these pros comes the cons due to some limits with using API Gateway. API Gateway has a default integration time out (a hard limit) of 29 seconds - which means the Lambda function needs to send back a response to API within this time frame or API fails with a 504 response. You may review other limits related to API Gateway here.
Approach #2 Lambda invoking Lambda
I'm not a big fan of this approach and have multiple reasons for it. I'll start with the additional code you have to write - same task with better features can be done by API Gateway with simple configurations on the AWS console.
A container calling another container(Lambda) can result it container-related problems - networking, container reuse and even managing IAM permissions properly.
Also, a Lambda function can be invoked by only three options - SDK, CLI or an entity that has "Invoke" permission. So basically, you need to have some kind of resource in front of your first Lambda to invoke it which will then invoke the second. In my opinion, API Gateway is the best front-end you can have for Lambda which is exactly AWS had in mind building these two services.
One of the pros I can think of this approach is the time out value - Lambda can run for up to max of 15 mins. Unless your client does not require a response back pretty quickly, you can run these two Lambda functions for a longer time to execute code.
Summary
All the above information was pretty general for anyone looking to use API Gateway and Lambda. I'll say it again that using API Gateway is a more convenient and useful approach however it may depend on your use-case. Hope this helps!

Use Application Load Balancer (ALB) to trigger Lambda functions, how to add a bit of authentication at the ALB level?

I have a React app which calls API gateway, which in turn triggers my Lambda functions. Now for saving cost purpose due to the potentially let’s say, tens of millions of requests to the API gateway, I did some research and are looking at to potentially use ALB to invoke my Lambdas rather than API GW. My API GW is simply a Lambda-Proxy integration.
My question is with API GW I can add API keys and custom authorizers etc, but for ALB, how do I add a bit of authentication at the ALB layer, say only allow the invocation of my Lambda functions only from the client that I trust? Note my client is a static React app with no server behind it! I don’t need anything too fancy but just want to reject requests other than my trusted request origins. Inside Lambda to cover browser I will just add CORS to response header. But at ALB level, how do I achieve what I required?
Looking forward to getting some shed of lights here!
Thanks
Is it an option using AWS Cognito or CloudFront? We did that with an Enterprise application which uses OIDC (OAuth 2.0). It does implement just Authentication for now.
Give a look in these links:
https://aws.amazon.com/de/blogs/aws/built-in-authentication-in-alb/
https://docs.aws.amazon.com/elasticloadbalancing/latest/application/listener-authenticate-users.html

Serverless - Options for communicating between services?

I have a few different services (generated by the Serverless Framework) that need to communicate between each other. The data is sensitive and requires authentication.
My current strategy is to create an api key for each service communicate between services using json web token like the token below.
fM61kaav8l3y_aLC/3ZZF7nlQGyYJsZVpLLiux5d84UnAoHOqLPu4dw3W7MiGwPiyN
What are some other options for communicating between services? Are there any downsides to this approach? To reiterate, the request needs to be authenticated and appropriately handle sensitive data.
Do you need sync or async communication?
A good approach would be to use events, because aws-lambda is designed as an event based system. So you could use SNS or SQS to decouple your services.
If you just want to make calls from one service to another you could invoke the lambda function directly via the aws-sdk see docs. So you would not add an API Gateways endpoint and your lambdas would stay private.
To better anwser your question you should give a short overview of your application and and an example of an interservice call you would make.
As I understand it, you intend to make the various functions in a given a service private. In doing so, each service will likely have serverless.yml file that resembles the following:
Image shows the setup for api keys used with a serverless framework rest api
While this is a suitable approach, it is less desirable than using ** Custom Authorizers**.
Custom Authorizers allow you to run an AWS Lambda Function before your targeted AWS Lambda Function. This is useful for Microservice Architectures or when you simply want to do some Authorization before running your business logic.
If you are familiar with the onEnter function when using ReactRouter, the logic among Custom Authorizers is similar.
Regarding implementation, since different services are leveraged to deploy various functions, consider deploying the function to AWS and noteing the ARN of the Lambda function. Follow these links to see the appropriate setup for the custom authorizer.
These images show the serverless.yml file for using custom authorizers when the authorizers are not part of the service but rather deployed on lambda already
The following github project aws-node-auth0-custom-authorizers-api/frontend is a good example of how to implement Custom Authorizers when the authorizer funciton is in the same service as the private function. Note your situation differs slightly yet you should expect their authorizer function logic to be simliar - only the project structure should differ

API Gateway Custom Authorizer - Get Source IP Address

Is it possible to get the source IP address of a request to your API Gateway in a 'Custom Authorizer' lambda function?
This is definitely possible with the actual integration of your API Gateway to a lambda function. Though it does not seem to be possible to get the requester's IP address in a Custom Authorizer function.
My goal is to do rate based blocking directly in APIG. A similar solution is described here. However, as I am only restricting access to one or two APIG endpoints, I'd rather do this in a custom authorizer function which simply adds the source address to the deny policy of the APIG when it reaches a rate limit.
EDIT: To clarify some potential confusion. I understand that I could do this through the regular integration as mentioned above, and in this other post. But I am trying to utilize the custom authorizer functionality, so that I don't have to write the same rate limiting code in all of my lambda functions.
You should look at
event.requestContext.identity.sourceIp
it will contain the original client IP.
When creating the Authorizer on the "Identity Sources" section add
Context: identity.sourceIp
and enable caching (default is 300 sec).
That way your authorizer lambda will not be called for each request, because it will cache the returned policy for that IP.
You can experiment yourself if you add logging of passed event parameter (just don't forget about caching, not all calls to API Gateway fire the authorizer lambda).
BTW, don't use "X-Forwarded-For" look at my comment on another #binshi's answer.
Custom Authorizers can now use so-called Enhanced Context.
You should be able to use the appropriate context variable to get that information (e.g. $context.identity.sourceIp).
You may also be able to use API Mappings, but I haven't tested that.
You can get the source ip as well as any proxy server ip in
events['headers']['X-Forwarded-For']

Amazon Lambda use cases

Is it possible to make some kind of HTTP request that will trigger Lambda and allow it to build a response for the request?
Is it possible for Lambda to access CloudFront cache directly or somehow get the data it needs. I guess it can be done making HTTP requests to CloudFront, but maybe there is more direct way to do that, no?
Or all this stuff I'm asking here is a peace of **** and I better go and buy a new server or optimize my code (actually, i would like to, but manager wants CloudFront + Lambda, so I'm trying to figure out if that is possible, but the docs don't give me an answer. Am I blind maybe?)
You can expose your lambda function via an API gateway. Then your lambda function can just run code that will access other services/resources (CloundFront, SNS, SQS, etc). Use the AWS SDK to access these services.
See Amazon API Gateway documentation: http://docs.aws.amazon.com/apigateway/latest/developerguide/getting-started.html