Getting Invalid mapping expression specified when setting GatewayResponse - amazon-web-services

The default API Gateway responses come in this form: {"message":$context.error.messageString}.
Changing this template via the console, to add wrap it in an "error" object for example, works fine. However, when I try it in CDK, it errors during deployment with Invalid mapping expression specified
Code (notice this is literally the default template):
webServiceApi.addGatewayResponse('4XX', {
type: apigw.ResponseType.DEFAULT_4XX,
responseHeaders: COMMON_HEADERS,
templates: {
'application/json': '{"message":$context.error.messageString}',
},
});
This happens with any change as well including all the AWS-written examples I could find. It's under-documented everywhere in AWS: CDK, SDK, API Gateway and CloudFormation so it's very difficult for me to figure out what's wrong there?
CloudFormation Error
Resource handler returned message: "Invalid mapping expression specified: Validation Result: warnings : [], errors : [Invalid mapping expression specified: *] (Service: ApiGateway, Status Code: 400, Request ID: [TRUNCATED], Extended Request ID: null)" (RequestToken: [TRUNCATED], HandlerErrorCode: InvalidRequest)

Apparantly the error was not with the mapping template, it was the headers needed to "'*'" for the origin instead of "*". That is NOT a useful error message

Related

AWS API Gateway to Simple Notification Service

I'm trying to use the AWS console to pass a message straight from an API Gateway into an SNS queue. All the examples I've seen seem to go via a Lambda, but all the documentation and settings seem to suggest this step isn't necessarily needed.
I've got the below setup, but keep getting the error of
Execution failed due to configuration error: No match for output mapping and no default output mapping configured. Endpoint Response Status Code: 400
The mapping template section has: "When no template matches the request Content-Type header" set which the "Help" section suggests the body (which is where the json string is posted) is passed through if I've got no template set up, but maybe I'm misunderstanding this.
What am I missing?

AWS API Gateway: Handle both invalid URL and validation errors

I have an API gateway set up with an OpenAPI specification and a proxy lambda integration. Request validation is enabled, and also an authorizer lambda.
Let's say I have endpoints GET /foo and POST /bar. The integrations to these endpoints work well, and the requests are validated and authenticated.
The problem is this:
In order to send back any validation errors when an invalid request is made, e.g. with a missing request body property, I have the following response mapping:
x-amazon-apigateway-gateway-responses:
BAD_REQUEST_BODY:
statusCode: 400
responseTemplates:
application/json: |
{"message": "Invalid request body: $context.error.validationErrorString"}
This also works well. However, if I try to call an endpoint that doesn't exist (e.g. GET /baz), I get a very weird default error message from API gateway. From the past I remember getting a HTTP 403 with something like "missing API key" for invalid URLs, which is weird since it should render a 404, but now I get the even stranger body:
{
"message": "'eyJhbGciOiJSUzI <rest of JWT ...>' not a valid key=value pair (missing equal-sign) in Authorization header: 'Bearer eyJhbGciOiJSUzI <...>"
}
In other words, the JWT I send as my bearer token is passed back in an error message, saying it's not a key=value pair.
Thing is, my authorizer lambda is only connected to the valid endpoints (obviously), so it's not being called. But why is the default built-in API gateway route handler parsing my bearer token and deciding it's not a key=value pair (!)? For an endpoint that doesn't exist? I don't have any {proxy+} endpoint at all.
If I try to map all 403 responses (MISSING_AUTHENTICATION_TOKEN, INVALID_SIGNATURE, etc) to custom error messages, as described here, I get no result, despite docs saying the default response for missing URLs is MISSING_AUTHENTICATION_TOKEN. However, if I also override DEFAULT_4XX, it works, I can return a HTTP 404 with a "Not found" message. The problem is that as soon as I override DEFAULT_4XX, it also overrides my BAD_REQUEST_BODY response so that my validation error messages are lost. Apparently DEFAULT_4XX is not matched last, it takes precedence over BAD_REQUEST_BODY!
How can I set up API gateway so that I at the same time can:
Return 404 NOT FOUND for invalid endpoints such as GET /baz
Return 400 with the $context.error.validationErrorString variable for requests that failed validation
I've found this question that described a similar problem, but surely it's not required to create a {proxy+} integration and/or a dedicated separate lambda only to return a 404 error, this must be possible to achieve by configuration!?
I used the openAPI mock proxy (no lambda) solutions documented here: not a valid key=value pair (missing equal-sign) in Authorization header
It is working very well.

Change response "not a valid key=value pair (missing equal-sign) in Authorization header" in AWS ApiGateway

I've read other similar posts with exact same error message, however my question is different.
I have an AWS ApiGateway in https://XXXXXXXX.execute-api.us-east-1.amazonaws.com/xxxx/users (from now I will call it as /users ).
I have implemented my ApiGateway to Lambda scripts with Cognito authorization, they work without problems, for example:
/users/me -> returns data of current logged user
The problem is when I call an unexistent route in ApiGateway, for example:
/users/mine123 -> it returns
{ "message":
"'my-cognito-user-id-token' not a
valid key=value pair (missing equal-sign) in Authorization header:
'Bearer my-cognito-user-id-token'." }
My question is... Is there a way to return a NotFound or BadRequest error when route in ApiGateway doesn't exist?
I think is possible implementing resource ANY, but, is there a "clean" way to do it without resource ANY?
Edit 1:
I tried Api Gateway response as well. I set a custom response, an status error code 404 for Resource Not Found but Api Gateway still returns 403 Forbidden.
Edit 2
I already have 4XX responses configured too:
And API Gateway always returns 403 error with this message (as expected for a generic 4XX error), however I think it doesn't make sense because is not a real Forbidden error it's a NotFound or BadRequest error.
For example,
A request to nonexistent route in Github API https://api.github.com/ROUTE_THAT_DOESNT_EXIST returns 404 NotFound.
A request to nonexistent route in StackExchange API https://api.stackexchange.com/ROUTE_THAT_DOESNT_EXIST returns 400 BadRequest.
None of them return 403 Forbidden.
Error message { "message": "token not a valid key=value pair Authorization header: 'Bearer token'. is thrown when "Resource path doesn't exist" with status 403 with a response header "x-amzn-ErrorType" = "IncompleteSignatureException"
A request with an "Authorization" header is sent to an API resource
path that doesn't exist.
We can customize response body in 'Gateway Response' section. There doesn't seem to specific Gateway Response like Unauthorized, Invalid Signature, etc for this scenario, Hence we need to configure Default 4XX
We can update status code and Response Templates. Unlike Integration Response on a successful request process, error gateway response template doesn't support full VTL template but only supports simple place holders.
Example configuration for application/json
{"message":"Invalid Resource","type": "$context.error.responseType","stage": "$context.stage"}
Will return
{
"message": "Invalid Resource",
"type": "DEFAULT_4XX",
"stage": "qa"
}
Not sure whether it is a cleaner way than your suggestion, however you can configure specific gateway response for the missing authentication token - https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-gateway-response-using-the-console.html
In the Gateway Responses pane, choose a response type. In this walkthrough, we use Missing Authentication Token (403) as an example.
You can change the API Gateway-generated Status Code to return a different status code that meets your API's requirements. In this example, the customization changes the status code from the default (403) to 404 because this error message occurs when a client calls an unsupported or invalid resource that can be thought of as not found.

How to pass AWS AccountId in REST API's uri(Cloudformation)

Code:
x-amazon-apigateway-integration:
uri: "arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:428377611111:function:${stageVariables.target_lambdaName}/invocations"
If use Pseudo Parameters like below i'm facing issue.
Updated Code:
x-amazon-apigateway-integration:
uri: "arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:${AWS::AccountId}:function:${stageVariables.target_lambdaName}/invocations"
Error:
Errors found during import: Unable to put integration on 'GET' for resource at path '/getMessage': Invalid HTTP endpoint specified for URI (Service: AmazonApiGateway; Status Code: 400; Error Code: BadRequestException; Request ID: 3da76bd8-d714-11e8-8ec4-4b324c6636a4)
Thanks in advance.
Naresh
First, you should remove your AWS Account ID from the question.
If you're using a SAM Template YAML file and passing variables to your template during your pipeline stage via ParameterOverrides you should then have parameters declared at the top of the file in your SAM Template YAML file and your code should be as an example POST.
paths:
/PATH_NAME:
get:
responses: {}
x-amazon-apigateway-integration:
uri:
Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${FUNCTION_NAME_HERE.Arn}/invocations
httpMethod: POST
type: aws_proxy
This is assuming this piece of code is attached to:
Type: AWS::Serverless::Api
Without any other information I'm just assuming what you're trying to do.
As a side note, you can access your account id in CloudFormation like so:
${AWS::AccountId}
Use of Pseudo Parameters in the SAM AWS::Serverless::Api resource has been documented in this realworld SAM example Github https://github.com/awslabs/realworld-serverless-application/wiki/Amazon-API-Gateway#use-awsserverlessapi-in-your-cloudformation-template
The example using AWS::Include allows the use of Pseudo Parameters in the swagger file.

AWS API Gateway: is it possible to include specific request body validation error in the response body?

I have an API Gateway POST endpoint that takes in a JSON request body. I have turned on the body request validator and added the request body model. However the error response I'm getting is only some generic message: "message": "Invalid request body" as defined in the Gateway responses. I'm wondering if it is possible to include the specific validation error in the response? In the logs it says specifically
Request body does not match model schema for content type application/json:
[object has missing required properties (["property1","property2",...])]
Is it possible to have something similar to this in the actual response? Thank you.
In Gateway response for error type BAD_REQUEST_BODY error status 400
set Application/json to {"message":$context.error.validationErrorString}
Ref
https://stackoverflow.com/a/48014686
AWS API Gateway will include more details only if the request payload format is valid, but parameters format is invalid:
{
"message": "Missing required request parameters: [p1]"
}
If the request payload is invalid, you will always receive the same message:
{
"message": "Invalid request body"
}
See the bottom of following page:
http://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-request-validation-test.html
The only way you can get more details is through logs.
By the way, why do you want to send more details through your API, is it for development and debugging only? If yes, using logs is the way to go. You may have some log processing and storage solution to make your debugging easier (e.g. Splunk, Data Dog, Sumo Logic, etc.)
Otherwise, in general, returning too much of technical details in your API error messages is something to avoid.