How to include context variables in AWS API-EventBridge Integration Detail body - amazon-web-services

I have an ApiGatewayv2 EventBridge-PutEvents Integration running. The POST body is sent into event bridge as the event Detail.
The Integration request parameters are as below:
{
'Source': 'com.me.api',
'DetailType': 'ApiEvent',
'Detail': $request.body,
'EventBusName': BUS_NAME,
}
If I post {"foo": "bar"} to the API endpoint, I end up with an event in my bus with {"foo": "bar"} as the Detail. So far, all straightforward.
I have also enabled an authorizer on the API GW and I want to pass the context from that authorizer into the event Detail as well.
I'm testing with an IAM authorizer for now, but would like to use Cognito.
I can update the request parameters to change the DetailType to $context.identity.caller and I get my Access Key in the DetailType of the Event.
This isn't what I want, but it shows that I can access these context variables in my integration.
What I want is for that to be in the Detail though - not the DetailType.
So, when I POST {"foo": "bar"} to my API GW I get an event with Detail:
{
"body": {"foo":, "bar"},
"auth": {"user": "AAA1111ACCESSKEY"}
}
But, I can't use anything other than $request.body as the Detail value in the Integration's request parameters.
If I use a Detail like {"body": $request.body} I get an error on saving the integration - Invalid selection expression specified: Validation Result: warnings : [], errors : [Invalid source: {"body": $request.body} specified for destination: Detail]
And, I've tried that with stringified {"body": $request.body} as well.
How can I wrap the POST data in a key like "body" within the event's Detail, and add key/values from the context variables I get from the authorizer.
Or, some other way to inject the authorizer context into my Event. Should I just give up and use a lambda to access the ApiGw context and run PutEvent? Seems defeatist!

This SAM template shows how to do what I wanted using an AWS REST API https://github.com/aws-samples/client-event-sample/blob/6d58777382da148a3ccc1314b0bdf21c46b6378f/template.yaml#L196
The rest api endpoint comes with the additional benefit that we can validate the inbound event json

Related

How to test an AWS API gateway that accepts form parameters sent in Http POST?

I am creating an API gateway in AWS that should accept a POST request from a form.
I want to test the API gateway as if it is receiving a POST request with form parameters. What I should add to the request body to conduct the test assuming that I have two form parameters "name" and "age"?
The web service accepts the parameters as #Formparams
You can add a json body like this there.
{
"name": "Test",
"age": 25
}
Based on the target service the name could be different for the body.
For instance, if the target is a Lambda function based on Node.js, the body can be found in event.body.

API Gateway - Allow passthrough only if number field is over a certain value

I have a simple webhook from a form that is sent to API Gateway and invokes a function every time. Our mapping template is very simple as shown below:
{
"number" : $input.json('number'),
"url" : $input.json('url')
}
DESIRED OUTCOME
Anything below 90 for the field number will not invoke the Lambda function and the webhook request is blocked/finishes at the API Gateway stage.
Is it possible to add some sort of filter so only number over 90 gets passed through and invokes the lambda function?
Yes, it is possible.
In order to do it, You have to enable AWS API Gateway Request Validation and write custom validator.
You can validate number field in this way:
"number": {
"type": "number",
"maximum": 90
}
You can find more information here:
Enable Request Validation in API Gateway
How to remove boilerplate validation logic in your REST APIs with Amazon API Gateway request validation

Use ApiGateway Authorizer to Validate Github Payload Signature (X-Hub-Signature)

I am currently working on a simple api to receive Github event payloads, and I want to validate that they are coming from the correct source. With this I am working to use the hmac signature in the requests header (generated by github using a secret provided by me). To validate the signature, the ApiGateway authorizer requires the signature (X-Hub-Signature), the secret used to generate the signature, and the body of the message. As far as I can tell, Api Gateway does not allow you to pass the body to an ApiGateway Authorizer. Does anyone know a way around this that does not require additional proxy lambdas and s3?
*Note: The requester is the Github Webhook service (not able to add body to header)
Basic ApiGateway Auth Docs:
https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-use-lambda-authorizer.html
Here is how you do it.
Pass your content to Authorization header of your incoming request, It will get delivered to your custom Authorizer.
Grab the contents of the from the below attribute,
event.authorizationToken
where event is one of the parameters (1st) passed to lambda,
I currently encrypt and add all the info to that header and gets delivered to the Custom Authorizer lambda.
You can also access additional parameters as below in your custom Authorizer lambda:
var headers = event.headers;
var queryStringParameters = event.queryStringParameters;
var pathParameters = event.pathParameters;
var stageVariables = event.stageVariables;
var requestContext = event.requestContext;
Hope it helps.

AWS ApiGateway Lambda Proxy access Authorizer

I´m using an Lambda Proxy and a Cognito User Pool Authorizer in my ApiGateway. In the Lambda function I can access the path etc. variables via the event object. In addition to that I want to access the claims of the authenticated user. In the documentation it is written, that I should use:
context.authorizer.claims.property
But I authorizer is null so I get
Cannot read property 'claims' of undefined
Anyone with an idea?
The accepted answer will work but it is not needed. When using Lambda Proxy Integration you can access the authorizer claims at:
event.requestContext.authorizer.claims
You can try to console.log(event); and see the information you get out of a Lambda Proxy Integration in CloudWatch Logs.
If you are referring to this part of the documentation, $context.authorizer.claims is part of the mapping template of the integration. It is not related to the context argument of the handler.
Using Lambda Proxy integration, you are using the passthrough mapping template. I̶t̶ ̶s̶e̶e̶m̶s̶ ̶w̶h̶a̶t̶ ̶i̶t̶ ̶d̶o̶e̶s̶ ̶n̶o̶t̶ ̶i̶n̶c̶l̶u̶d̶e̶ ̶w̶h̶a̶t̶ ̶y̶o̶u̶ ̶a̶r̶e̶ ̶l̶o̶o̶k̶i̶n̶g̶ ̶f̶o̶r̶ (see edit). You'll probably have to disable Lambda Proxy integration and use something like this in the mapping template:
{
"identity" : {
"sub" : "$context.authorizer.claims.sub",
"email" : "$context.authorizer.claims.email"
}
}
The mapping template "build" the event parameter of the Lambda. So you will be able to access to the parts of your claim via the event parameter.
exports.handler = (event, context, callback) => {
// TODO implement
callback(null, event.identity.email);
};
Note that I slightly modified the documentation example to avoid another confusion about what context can be:
the mapping template variable in API Gateway
the second argument of a handler in Lambda
a key of the event argument in some examples of the documentation <= I renamed it identity
Edit
As pointed out by doorstuck, the information is available using the proxy integration
Ensure you are sending the "Identity Token" as the Authorization header instead of the "Access Token".
Documentation for Identity Token
For example, I am using Amplify and was getting the access token with:
userSession.getAccessToken().getJwtToken() // Wrong
instead of
userSession.getIdToken().getJwtToken() // Correct

AWS API Gateway - How to create a post method and test it

My scenario is when my Lambda function's Api endpoint is hit, with a post variable, i want my Lambda to invoke a database connection and get some results.
So the first step is to create an API Gateway endpoint and I have problem creating the POST method with parameters
Here is what i did till now:
Created a API Endpoint for my Lambda Function.
When i go into the POST Method in Lambda's API endpoint section, i am taken to this screen
When i Test the function from the AWS Console,
and response is as follows in the console
How do i create parameters for the api here? and how do i test it? I have my lambda function ready, that takes in a String as input and returns a String as response.
Can someone guide me for the next steps..
You can check the Create and Test a POST Method
you do not mention the parameters in the lambda definition, the parameter will be taken from the request directly (so in future if you change your lambda code to take new parameters, you dont need to change the configuration
To test :
In the Method Execution pane, in the Client box, and then choose TEST.
Expand Request Body, and type the following:
{
"name": "User" <or any other parameter that you expect>
}
Choose Test. If successful, Response Body will display the reply from
your lambda execution
For example here an example post api I had
so again for POST API you dont define the parameters
If you were doing GET API you would define the query parameters
Great step by step explanation of Serverless API on AWS: Serverless API on AWS in 10 minutes
The answer by Frederic is very good, I'll just leave another example in the docs -> http://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html
Further down on that page is an example for Param Mapping which will proxy any incoming parameters to Lambda. You still need to explicitly state any incoming parameters that you expect clients to send in the Method Request.