API Gateway Custom Authorizer - Get Source IP Address - amazon-web-services

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']

Related

What is the simplest way to secure my lambda's functionURL?

I have a lambda that needs to be accessed by a user. They must be able to visit the URL in a browser. What is the simplest way to secure the functionURL so that if the URL were to leak, there would be another layer of security that would need to be gone through?
I can't use AWS_IAM as the requirement is that the user clicks on the link and I can't expect them to deal with AWS SigV4.
A simple solution would be using the queryparams and adding an access code parameter that is checked for when the lambda is called but this seems like a bad idea for various reasons.
Lambda function URLs only support AWS_IAM and NONE for the AuthType parameter, as mentioned in the documentation.
I can't use AWS_IAM as the requirement is that the user clicks on the link and I can't expect them to deal with AWS SigV4.
Then you need to use an AWS API Gateway, and place your lambda function behind it.

Restrict Lambda function URL access to CloudFront

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

AWS API Gateway proxy with AWS Lambda as middle ware

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

AWS Lambda (URL) rewrite flow

I am new to Lambda so I would like to understand how the following scenario can be deployed:
Lambda connected to API gateway ( which in turn connected to a reverse proxy)
The request from API gateway to lambda needs to be routed to 3 different ALBs each in different (VPCs) private subnets.
What configuration changes I need to bring in to achieve this apart from writing Lambda function (using python) to rewrite the urls?
It would be nice if someone can explain the message flow here.
Thanks
Abhijit
This to me seems to be multiple issues, I'll try to break down whats trying to be achieved.
Using ALBs with API Gateway
There are many options for how API Gateway can use load balancers to serve http traffic. The solution really depends on which type of API Gateway you are trying to use.
Assuming your API is either REST or WebSockets you are left with 2 choices for enabling HTTP traffic inbound to a load balancer:
Directly as a HTTP or HTTP_PROXY request, listing publicly accessible hostnames to which API Gateway will forward the traffic.
If you want to keep transit private then your only option is to create a network load balancer and make use of VPCLink to create a private connection between API Gateway and your Network resource.
If you're creating a HTTP API (sometimes referred to as API Gateway v2) then you can make use of direct connection to a private ALB, however be aware that at this time HTTP API does not support all the features of REST APIs so you would want to compare feature sets before doing this.
Using multiple load balancers to direct traffic
You determine the value per each resource/method combo, for example POST /example would be assigned its target endpoint, but only one.
My suggestion would be to make use of stage variables if you're using a REST API to specify any endpoints that you're forwarding traffic for the following reasons:
Prevents mistyping of domain names
Allows quick replacement of a hostname
Provides functionality for canary deployments to shift traffic proportionally between 2 variable names (these could be anything as long as the type is the same e.g. Lambda to another Lambda, not Lambda to a load balancer).
Using a Lambda to redirect
Technically a Lambda can perform a redirect by return a response using the below syntax
{
statusCode: 302,
headers: {
Location: 'https://api.example.com/new/path',
}
}
However be aware this will change the request to become a GET request, this will also remove the payload of the body request when the redirect occurs. Additionally you would need to set this up for every resource/method combo that you wanted to redirect.
There are 2 options that you have available to get around these issues, both involve using CloudFront combined with a Lambda#Edge function.
The first solution can act as a workaround for the request type changing, in the Origin Request event you could modify the Request URI property to match the new URI structure. By doing this your clients would be able to use the API still, whilst you would notify them of the depercations to certain paths that you were migrating.
The second solution acts as a workaround for the need to add redirects to each resource/method combo which can create a lot of mess of methods just for redirects. You could create a Lambda#Edge function to perform the same redirect on an Origin Response event. You could create mappings in your Lambda function to work out which URL it should redirect to.
There are many great examples on the Lambda#Edge example functions page

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