Can event.requestContext.identity.cognitoIdentityId be spoofed? - amazon-web-services

I'm trying to do ACL by asserting if the item in DynamoDB whose field UserId is really the one logged in which is event.requestContext.identity.cognitoIdentityId.
But, I'm afraid that it can be spoofed just like HTTP headers etc.
My question is, is that safe?

No, this cannot be spoofed in the same way HTTP request headers can. If the request comes in through API Gateway, as a Lambda proxy integration, then there's nothing the browser can do that would allow these values to be overwritten, because this portion of the Lambda event structure is created by API Gateway and not copied from the request. Anything injected into the HTTP request would appear elsewhere in the event structure -- not here. (The HTTP request is in event.input -- which is a sibling object of event.requestContext -- not a parent.)
But then again... yes, this could be spoofed in certain other misconfiguration scenarios -- if, for example, your Lambda function allows itself to be invoked other than by your API Gateway deployment -- then of course the invoker could craft an entire event structure that had nothing to do with any HTTP request and invoke your Lambda function with it. This is perhaps too obvious to mention, since it's implicit from the way you can test a Lambda function from the console, but I mention it for thoroughness. Send a forged test event to your Lambda function using the Lambda console's test function, and naturally the Lambda function processes what you sent it.
So, unsurprisingly, with careless and overly broad permissions, yes, anything is possible... but used as intended behind API Gateway, as a Lambda Proxy Integration, I'd say no.

I have been researching this question for many hours.
I found this post where the author extracts the userId from the Token via:
const userId = await services.getUserIdFromToken(event.headers.Authorization);
This appears to be a safer way to handle setting the userId but all the other examples I have seen use event.requestContext.identity.cognitoIdentityId.

Related

Creating an AWS lambda that calls a rest endpoint

I want to create a simple AWS lambda that makes a url request to a rest endpoint. The thing I’m not sure about is I know for lambdas the response size limit is 6mb, and the response that comes back from the rest endpoint I intend to have it call fluctuates and sometimes can go beyond that limit.
I don’t necessarily need to return the response from the rest endpoint that the lambda will make a call to, but rather I feel like I can have the lambda write the contents of the response into a database instead of returning it, and then just return a response code at the end. I was wondering if this workaround will work or will I still have issues with the 6mb size limit on some manner?
Still in the prototyping phase, just a general question that I can elaborate more on if necessary

How to invoke lambda when lex does not process the intent automatically?

My Lex bot has four intents. Suppose a user asks a question at the very beginning of the conversation and this question is not allotted to any of the four intents. Hence no intent will be established. When this happens, I want to call lambda to run an "intent suggestion model" (built using topic modeling) to suggest the user about what the intent of the question might be. Also, lambda will have to store such queries in a database (s3 or RDB) so that if such queries are repetitive, then that intent can eventually be added to the bot and for other analytical solutions.
What you need is a fallback intent but Lex does not support fallback intents as of now.
You can still achieve this if you use a bridge between your chat client and Lex.
Setup an API Gateway and Lambda function in between your chat-client and the Lex.
Your chat-client will send a request to API Gateway, API Gateway will forward this to Lambda function which will be used to call Lex and get response from it. Lex will have one more lambda function as a webhook.
In the Lambda function you used to call Lex, we can check if any intent was matched or we got an error message, if it's an error message and trigger some action like intent suggestion model.
You need to use boto library to call Lex and use post_text() method.
Hope it helps.

Can you modify the URI on an AWS CloudFront event with Lambda#Edge in a language other than Javascript?

I'm trying to do some AB testing and inserting a Lambda in our AWS CloudFront setup seems a good way to do it. My company has problem with NodeJs. They were burned by some old devs using it and have banned its use.
Lambda supports a bunch of languages so no big deal. But after some research and looking at the source. Only the Javascript seems to be able to interact with CloudFront events and passing the request forward. All the libraries for other languages seem to only emit response events and don't allow for the passing forward of the request after modification.
Am I missing something or is this scenario only supported with JS?
Lambda#Edge supports only Node.js runtimes.
You must create functions with the nodejs6.10 or nodejs8.10 runtime property.
https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/lambda-requirements-limits.html#lambda-requirements-lambda-function-configuration
Your observation about other runtimes "seem to only emit response events and don't allow for the passing forward of the request after modification" isn't really an accurate representation of what happens. Node.js doesn't do any special "passing forward" magic. CloudFront interprets the response payload from the Lambda function to determine how to proceed. If it's a request trigger and the Lambda function returns something structured like a request, then CloudFront continues processing the request, as modified. Otherwise CloudFront interprets the response payload as a response to be returned to the caller. Everything is handled by CloudFront's interpretation of what the Lambda function returns.
Any Lambda runtime could theoretically have accomplished the same purpose, but Lambda#Egde was designed for -- and currently only supports -- the Node.js runtimes, which are lightweight and fast, as they need to be, because CloudFront invokes the trigger function synchronously and then blocks (suspends its own processing) while waiting for the function to return.

Can AWS API Gateway cache invalidate specific entries based on the response content?

I have used AWS API Gateway with the endpoint as a lambda function. I have enabled the cache functionality provided by API Gateway, to reduce both response time & the number of calls forwarded to my lambda function.
The lambda function queries another data store to return data. If data is not found, an asynchronous call is made to update the data store and "data not found" is returned to the caller. Now the API Gateway is even caching this result, which we do not want to happen. This results in the cache always returning "data not found" for its lifetime (1 hr TTL), even though data is updated asynchronously in the data store.
I'm aware of the request header (Cache-Control: max-age=0) which can invalidate cache and get response directly from Lambda, as mentioned in this documentation page.
But this will not be useful because the caller is unaware whether data is present in data store or not and hence cannot selectively send such request header.
So, my 2 questions are:
Does the API Gateway caches other HTTP response as well, like 404 (apart from 200)?
Is it possible to tell the API Gateway not to cache specific responses?
As you observed, API Gateway caches the result of your endpoint regardless of the status code.
No, not at this time. I can bounce the idea to see if this is something we can support in the future.
Even if API Gateway conditionally did not cache the 404, the caller would need to call the endpoint again anyway, so why not return the result synchronously? This pattern is how most cached APIs that I'm aware of behave and would allow your API to work with what API Gateway offers today.

Access web within AWS Lambda

I'd like to define a lambda. When it receives a POST request, I'd like to make another POST request to an external uri (say, splunk or apigee or anything outside of AWS). Is this possible? Does Lambda allow the internet access? I googled but did not find a good answer for this one.
Yes, you can run pretty much any code that you would run on a normal EC2 instance. For instance, if you write your Lambda in node.js you can use the request library to make HTTP calls out to other webservices. The same is true of Java or Python as long as you include whatever library you want to use to make the call in your Lambda. Just make sure you set the Lambda timeout high enough to allow your call(s) enough time to complete.
I wrote a blog post that shows a simple example of a Lambda calling out to a weather API(HTTP GET) to get weather for a zip code and post it in Slack: http://www.ryanray.me/serverless-slack-integrations