Passing context / authorisation with cloudfront to lambda - amazon-web-services

This is bit tricky situation I got into here,
I set up a lambda function & API gateway, then I setup cloudfront over API gateway for faster processing and achieving benefit of all the endpoint nodes provided by AWS [It should take more time using cloudfront on top of API gateway service but I am getting better result with cloudfront layer on top of it, maybe DNS resolution and AWS internal infrastructure is better]
I setup a JAVA function inside lambda which is working perfectly fine, but I want to use Context of request maker in lambda function
public String handleRequest(UserPOJO input, Context context) {
}
If I make direct lambda function request I can achieve that but it's taking too much time executing direct lambda from my Android client, also I don't find it good to expose those details, and with cloudfront I am not sure what headers should I send so that lambda detects it's cognito role and ID using context.getIdentity().getIdentityId(); in lambda.
If someone understands my problem here and elaborate it better for other I will be glad, it is very complex to explain the problem.
Technically
I can make execution of lambda function directly with cognito credential provider authentication but Very slow
Can make API gateway request which cognito credential provider authentication, speed is better than direct lambda execution
Can make cloudfront request but stuck where I don't know how can I use cognito credential provider authorisation while making the request. Seemed faster than API gateway.
Thanks. :)

If you want to get Cognito related information in Lambda function and you are proxying your request from API Gateway, You can use the mapping template to include information you need, then you can get it from the input object.
I can make execution of lambda function directly with cognito credential provider authentication but Very slow.
I recommend you to build your Lambda function in python or javascript runtime.
Can make API gateway request which cognito credential provider authentication, speed is better than direct lambda execution
API Gateway cannot improve the performance of your Lambda function, but API Gateway can provide API management feature for your Lambda function.
Can make cloudfront request but stuck where I don't know how can I use cognito credential provider authorisation while making the request. Seemed faster than API gateway.
CloudFront doesn't have do anything with your Cognito credential. It just passes everything it gets to API Gateway.
I am not sure how adding a CloudFront distribution in front of API Gateway can make the latency better except you enable the edge side cache which is not calling your Lambda function every time.

Related

Prevent AWS Lambda flooding

I'm considering about moving my service from a VPS to AWS Lambda + DynamoDB to use it as a FaaS, because it's basically 2 API GET calls that fetch info from the database and serve it, and the normal use of those API calls are really rare (about 50 times a week)
But it makes me wonder... As I can't setup a limit on how many calls I want to serve each month, some attacker could theoretically flood my service by calling it a couple thousands times a day and make my AWS bill extremely expensive. Setting up a limit per month wouldn't be a nice idea either, because the attacker could flood the first day and I won't have more requests to serve. The ideal thing would be to set up a limit on request rate per client.
Anyone knows how could I protect it? I've seen that AWS also offers a Firewall, but that's for CloudFront. Isn't there any way to make it work with Lambda directly?
You can put AWS CloudFront in front API Gateway and Lambda so that, the traffic will be served to outside through CloudFront.
In addition by configuring AWS WAF with rate base blocking, it is possible to block high frequencies of access by attackers.
However when configuring AWS CloudFront in front of API Gateway and Lambda, you also need to restrict direct access to API Gateway (Since API Gateway will be publicly accessible by default). This can be achieved in following ways.
Enable API Keys for API Gateway and use the API Key in AWS CloudFront Headers in the Origin.
Use a Token Header and Verify it using a Custom Authorizer Lambda function.
Two options spring to mind:
place API Gateway in front of Lambda so that API requests
have to be authenticated. API Gateway also has built-in throttles and other useful features.
invoke the Lambda directly, which will require the client
invoking the Lambda to have the relevant IAM credentials.

How to secure the APIGateway generated URL?

I have a serverless backend that operates with APIGateway and Lambda. Here is my architecture:
Currently, anyone with my APIGateway's URL can query or mutate the data. How do I protect the URL, so that only the client(react app) can access it. So, here is my concern, anyone can open the network tab in chrome console and get my APIGateway's URL and can use it using curl or postman. I want to prevent that.
Solutions I had in my mind:
Set up a CORS, so that only the origin can access it. But, I have a different lambda that invokes this URL. So, CORS wont work out.
I am sure there are some methods with the APIGateway itself. I am not getting right search term to get it from AWS documentation. I would also like to know what are the best practices to prevent accessing the backend URL apart from the Client(React App)
Update after #Ashan answer:
Thank you #Ashan for the answer. In my case, I use Auth0, so custom authoriser should work for me. I just came across this https://www.youtube.com/watch?v=n4hsWVXCuVI, which pretty much explains all the authorization and authentication possible with APIGateway. I am aware that authentication is possible either by Cognito/Auth0, but I have some simple websites, that has form, whose backend is handled by APIGateway. I can prevent the abuse from scraping bots using captcha, but once the attacker has got the URL, header and request parameters, he can invoke that million times. One thing, we can do is having an API-Key, but it is a static string with no expiration. Once the headers are with him, he can abuse it. So, any idea, how to prevent this in APIGateway. If not any other service apart from AWS that I can look for? Would be glad, If I get an answer for this.
Currently API Gateway does not support private urls, so it will be publicly available.
To restrict access you need to use a authorizer to authenticate and authorize the request using IAM policies. There are two options available at the moment.
IAM authorizer
Custom authorizer
If your authentication flow can directly (AWS STS, IAM user access keys or roles) or indirectly(Using AWS Cognito Userpools or any other SSO provider) can get temporary security credentials, then you can use IAM authorizer. From API Gateway side no code involved and its a matter of selecting the IAM check box for each API Gateway resource. You can use the API Gateway SDKs to invoke API Gateway requests where the SDK will handle the heavy liftings in setting up authentication headers.
If you use your own authentication mechanism, then you can write a seperate Lambda function to validate the tokens. This Lambda function name can be specified at API Gateway with the http hearder name to access the custom token to verify the requests.
To control API usage by authorized consumers, using API Key is the only way native to AWS at the moment.
Since you are using S3 for the react app hosting, you can further reduce the attack surface by using AWS WAF and CloudFront infront your application stack. The API Key can be added to CloudFront headers to forward to your APIGateway origin and since CloudFront and APIGateway communication happens using SSL, its nearly impossible for someone to find the API key. Using AWS WAF you can limit malicious access for common attacks. This includes rate based blocking to limit someone from repeatedly invoking the API.

How to make Aamzon API Gateway accept requests only from specific host

So my problem is I have a lambda function created in AWS Lambda and is linked to the api gateway. So I want to make sure the request to the lambda function only happens throug my domain www.example.com
In this domain I make a request to run the serverless lambda function to perform a specific task.
Is there a way to ensure the api request is accepted only from my domain or host.
Also I make use of Python 2.7 to write the lambda function if there is any alternative please do suggest me, I am new to python and AWS Lambda.
If you are worried about browsers making requests to your api on www.example.com, that shouldn't happen if you don't have CORS headers that allow other domains to make requests. But outside of a browser, anyone can still make requests to your APt.
You can however authenticate api calls. This can be a simple api key thats on your client or temporary credentials (call STS to get credentials for a role) to call your api. But with effort someone (look at your source code and replicate the calling mechanism) can still call your api. You could increase the level of effort required, if you only allow authenticated users (authenticated using some name/password and enforced on api gateway) to make api calls.
If you are worried about being over billed, you can setup a usage plan on your api key and restrict it to x number of calls a day/week/month.
API Gateway supports multiple authentication mechanisms
IAM Auth https://aws.amazon.com/premiumsupport/knowledge-center/iam-authentication-api-gateway/
API Key http://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-setup-api-key-with-console.html
Cognito user pools http://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-integrate-with-cognito.html

Accessing client context in a Lambda function via API Gateway

I've created a Lambda function, and connected it to an API Gateway endpoint. My users are authenticating using Facebook via Cognito (so, obviously using a Federated Identity Pool). In my iOS app, I am able to authenticate properly, receive a Cognito Id back, and also properly execute my Lambda function by way of API Gateway.
Where I'm stuck now is attempting to access the user's identity in my lambda. I understand from other threads & the AWS docs that I should use able to access the identity via context.identity.cognitoIdentityId in JS. However, the context is always null.
Further digging suggested that the context is passed in the X-Amz-Client-Context header -- when I look at packets for the API Gateway call, I do not see that header being passed through. I am using the automatically generated SDK (ObjC) from Gateway for my endpoints.
What am I missing here?
I apologize for the confusion. You have 2 options for getting this value into your lambda function:
By passing via API Gateway. If you are using the Lambda Proxy, it should already be available in event.requestContext.identity.cognitoIdentityId.
By enabling use caller credentials in your integration. If you use this method, you will also need to add lambda:Invoke permissions to your Cognito role.

Limt AWS API Gateway endpoint with GET parameters

I have an API Gateway endpoint at some url, like this:
https://api.myapp.com/myendpoint
The people and/or services that are going to be accessing this endpoint need to pass particular parameters and values to the endpoint. Like this:
https://api.myapp.com/myendpoint?token=123456
Is it possible to limit access to the endpoint if the token parameter is missing OR if the token value is not a specific pre-determined value? Can I setup my endpoint to simply ignore calls that don't have the proper token?
I'm planning on using Lambda as the backend. Do I have to deal with this in my Lambda function? Ultimately, I'm trying to avoid unnecessary Lambda and API Gateway usage costs by random individuals making bogus calls to the endpoint. So if I can have API Gateway simply ignore these calls without spinning up Lambda that would be ideal.
If I am able to have API Gateway ignore these calls, do I still get billed for usage when bogus calls are made to the endpoint(s) that are missing the token?
The reason I'm asking is because the 3rd party service that is going to access this endpoint does not have any options for passing authentication parameters in headers or using AWS Cognito, etc. So I'm just trying to think of a simple way to limit access.
You will need to perform this validation in Lambda.
If you have a mapping for a query parameter token to the integration endpoint, then for a request like ...?token=123 API Gateway will pass the parameter to the endpoint, but for ...?token=, API Gateway will not.
API gateway does not do validation of query parameters like you want and you will be billed for the requests.