Solving 500-Integration Error with Amazon API Gateway and Lambda - amazon-web-services

I have created a lambda instance, then used the 'automagic' button in lambda to create an http API gateway. I have modified the log output within the API Gateway instance, but not much else. When I call it within my application, I'm getting an intermittent error (API Gateway log):
{
"requestId": "xxxx",
"ip": "xx.xx.xx.xx",
"requestTime": "10/Jan/2020:18:47:08 +0000",
"httpMethod": "GET",
"routeKey": "/Current",
"status": "500",
"protocol": "HTTP/1.1",
"responseLength": "35",
"error": "Internal Server Error",
"error response type": "INTEGRATION_FAILURE"
}
When this happens, it doesn't seem to be hitting the lambda instance at all (duh! integration failure!). Or at least there's nothing in the lambda log.
But if I reload the web page that makes the call a couple of times, the error no longer appears.
Does the lambda instance need to 'wake up'? I tried a 'pre-call' within my application, under the assumption that this was the case and it didn't seem to help.
What is happening and what can I do to avoid the blank screen my customer is seeing?
UPDATE: I have checked the permissions, and run the command necessary to make sure they are correct:
aws lambda add-permission \
--statement-id [statement id] \
--action lambda:InvokeFunction \
--function-name [lambda function name] \
--principal apigateway.amazonaws.com \
--source-arn [source arn]
It didn't help.

Did you by any chance configure an authorizer that's piped into the API Gateway?

Related

The Vpc link is not yet available for deployment

I am following the instrutions at https://aws.amazon.com/getting-started/projects/build-modern-app-fargate-lambda-dynamodb-python/module-four/
aws apigateway create-deployment --rest-api-id a2kpkzqme1 --stage-name prod
An error occurred (BadRequestException) when calling the CreateDeployment operation: The Vpc link is not yet available for deployment
I had the same issue. So I checked the status of creation of the VPC Link:
aws apigateway get-vpc-link --vpc-link-id MY_VPC_LINK_ID
It showed, that creation failed:
{
"id": "xxxxxx",
"name": "MysfitsApiVpcLink",
"targetArns": [
"arn:aws:elasticloadbalancing:MY_REGION:MY_ID:loadbalancer/net/mysfits-nlb"
],
"status": "FAILED",
"statusMessage": "NLB ARN is malformed",
"tags": {}
}
So the failure I made was a wrong NLB ARN. I forgot something at the end.
I repeated all steps from the creation of the VPC Link (with right NLB ARN). Then it worked for me.

Cognito User Pool - Post confirmation trigger, access denied exception

I am crating a Cognito user pool using GO SDK, I am using the API CreateUserPoolInput.
I have a post confirmation trigger, for this lambda function.
So when the user confirmation happens, this lambda function is expected to trigger.
But I am getting an error - Access denied.
When I login to AWS console and re-configure this lambda function for this trigger, it works.
Reference -
https://forums.aws.amazon.com/thread.jspa?messageID=748566
I want to provide the invoke permission using the AWS APIs.
Is there any API or code example, which I can refer to provide the required access?
I am not familiar with GO, but from an AWS API perspective, what happens when you use the AWS console to add a trigger to a lambda function, you effectively add permission for another service to invoke your function. The AWS graphical console calls the underlying API under the scene to make it easy to use.
If you are creating or configuring a Lambda function using the AWS CLI or an SDK, you need to make an explicit call to the add-permission API.
Here is the doc for the AWS CLI. It is a nice way to practice and discover before to start to write your code : https://docs.aws.amazon.com/cli/latest/reference/lambda/add-permission.html
Here is the doc for the Go SDK equivalent : https://docs.aws.amazon.com/sdk-for-go/api/service/lambda/#Lambda.AddPermission
And here are two examples in bash shell (one to authorize API Gateway and one to authorize Amazon S3 to trigger a function, but I am sure you can adapt this easily to your use case)
aws lambda add-permission \
--region $REGION \
--function-name $FUNCTION_NAME \
--statement-id 1 \
--principal apigateway.amazonaws.com \
--action lambda:InvokeFunction \
--source-arn arn:aws:execute-api:$REGION:$ACCOUNT_ID:* >/dev/null
#
# Add permission to authorize S3 bucket to invoke Lambda
#
AWS_ACCOUNT_ID=$(echo $ROLE_EXEC_ARN | sed 's/^arn:aws:iam::\(.*\):.*$/\1/')
aws lambda add-permission --function-name $FUNCTIONNAME --region $REGION --profile $PROFILE --statement-id Id-x --action "lambda:InvokeFunction" --principal s3.amazonaws.com --source-arn arn:aws:s3:::$BUCKETNAME --source-account $AWS_ACCOUNT_ID
I was able to solve this issue using the AddPermission API call.
Here is the code snippet.
actionString := "lambda:InvokeFunction"
principalString := "cognito-idp.amazonaws.com"
sourceArn := userPoolArn
statementIdString := "cognitoaddpermission"
addPermissionInput := &lambda.AddPermissionInput{
Action: aws.String(actionString),
FunctionName: aws.String(lambdaFunctionName),
Principal: aws.String(principalString),
SourceArn: aws.String(sourceArn),
StatementId: aws.String(statementIdString),
}
resultAddPermission, errAddPermission := lambdaSessionClient.AddPermission(addPermissionInput)

AWS API Gateway WebSocket Connection Error

I created an API by AWS API Gateway and Lambda that is same 'https://github.com/aws-samples/simple-websockets-chat-app'. But the API not working trust. I get an error when i try to connect. Its message is "WebSocket connection to 'wss://b91xftxta9.execute-api.eu-west-1.amazonaws.com/dev' failed: Error during WebSocket handshake: Unexpected response code: 500"
My Connection Code
var ws= new WebSocket("wss://b91xftxta9.execute-api.eu-west-1.amazonaws.com/dev");
ws.onopen=function(d){
console.log(d);
}
Try adding $context.error.validationErrorString and $context.integrationErrorMessage to the logs for the stage.
I added a bunch of stuff to the Log Format section, like this:
{ "requestId":"$context.requestId", "ip": "$context.identity.sourceIp",
"requestTime":"$context.requestTime", "httpMethod":"$context.httpMethod",
"routeKey":"$context.routeKey", "status":"$context.status",
"protocol":"$context.protocol", "errorMessage":"$context.error.message",
"path":"$context.path",
"authorizerPrincipalId":"$context.authorizer.principalId",
"user":"$context.identity.user", "caller":"$context.identity.caller",
"validationErrorString":"$context.error.validationErrorString",
"errorResponseType":"$context.error.responseType",
"integrationErrorMessage":"$context.integrationErrorMessage",
"responseLength":"$context.responseLength" }
In early development this allowed me to see this type of error:
{
"requestId": "QDu0QiP3oANFPZv=",
"ip": "76.54.32.210",
"requestTime": "21/Jul/2020:21:37:31 +0000",
"httpMethod": "POST",
"routeKey": "$default",
"status": "500",
"protocol": "HTTP/1.1",
"integrationErrorMessage": "The IAM role configured on the integration
or API Gateway doesn't have permissions to call the integration.
Check the permissions and try again.",
"responseLength": "35"
}
try using wscat -c wss://b91xftxta9.execute-api.eu-west-1.amazonaws.com/dev in a terminal. This should allow you to connect it. If you don't have wscat installed, just do a npm install -g wscat
To get more details, enable logging for your API: Stages -> Logs/Tracing -> CloudWatch Settings -> Enable CloudWatch Logs. Then, send a connection request again and monitor your API logs in CloudWatch. In my case, I had the next error:
Execution failed due to configuration error: API Gateway does not have permission to assume the provided role {arn_of_my_role}
So, I added API Gateway to my role's Trust Relationships, as it's mentioned here and it fixed the problem.

Unable to Invoke AWS Lambda Function in Amazon Connect Contact Flow

I am trying to Integrate AWS Lambda function in Amazon Connect Contact flow. The AWS Lambda function is working fine and giving a response. While invoking the function in the Connect contact flow, it is returning error statement but I am unable to find out what is the error and where the error log is storing.
I am trying to get the user's phone number to the Amazon Connect and then I would like to check whether the phone number already exists in the DynamoDB or not. For this, I am writing the lambda function and trying to invoke it from Amazon Connect
const AWS=require('aws-sdk');
const doClient=new AWS.DynamoDB.DocumentClient({region: 'us-east-1'});
exports.handler = function(event, context, callback) {
var params={
TableName:'testdata',
Key: {
Address: event.Details.ContactData.CustomerEndpoint.Address
}
};
doClient.get(params,function(err,data){
if(err)
{
callback(err,null);
}
else
{
callback(null,data);
}
});
}
First, you need to make sure permissions have been granted properly. From AWS CLI, issue the following command with the following edits.
Replace function "Lambda_Function_Name" with the actual name of your Lambda function.
Replace the source-account "111122223333" with your AWS account number
Replace the source-arn string with the arn string of your Amazon Connect instance.
aws lambda add-permission --function-name function:Lambda_Function_Name --statement-id 1 --principal connect.amazonaws.com --action lambda:InvokeFunction --source-account 111122223333 --source-arn arn:aws:connect:us-east-1:111122223333:instance/444555a7-abcd-4567-a555-654327abc87
Once your permissions are setup correctly, Amazon Connect should be able to access Lambda. You must, however, ensure that your Lambda function returns a properly formatted response. The output returned from the function must be a flat object of key/value pairs, with values that include only alphanumeric, dash, and underscore characters. Nested and complex objects are not supported. The size of the returned data must be less than 32 Kb of UTF-8 data.
Even with logging enabled on your call flow, Amazon Connect doesn't provide very detailed information about why a Lambda function fails. I would recommend hard coding a simple response in your Lambda function such as the following node.js response to ensure your Lambda response format isn't causing your issue and then work from there.
callback(null, {test : "Here is a valid response"});
When you are using the "Invoke AWS Lambda function" step, you do not need to pass the phone number to Lambda as a separate parameter as your image shows. Amazon Connect already passes a JSON object to Lambda that contains that information. Below is a sample of what Amazon Connect sends to Lambda.
{
"Details": {
"ContactData": {
"Attributes": {
"Call_Center": "0"
},
"Channel": "VOICE",
"ContactId": "",
"CustomerEndpoint": {
"Address": "+13215551212",
"Type": "TELEPHONE_NUMBER"
},
"InitialContactId": "",
"InitiationMethod": "INBOUND",
"InstanceARN": "",
"PreviousContactId": "",
"Queue": null,
"SystemEndpoint": {
"Address": "+18005551212",
"Type": "TELEPHONE_NUMBER"
}
}
},
"Name": "ContactFlowEvent"
}
You can use the following in your Lambda function to reference the calling number to lookup in your DynamoDB.
var CallingNumber = event.Details.ContactData.CustomerEndpoint.Address;
Hope this helps.

Create api-gateway lambda integration using aws-cli

I need to create an api gateway using aws client. I successfully create and integrate with my aws-lambda function using web console. But I am confused with aws-client. These are the steps I followed.
Create api gateway and integrate with my sample lambda function using web console.
Deploy created api and export as json file.
Create new api gateway using exported json file using aws-cli. Command like this.
aws apigateway import-rest-api --body file://tmpfile.json --region us-east-1;
But it created only resources & methods.
For integrate api method with my lambda function, I execute command like this
aws apigateway put-integration --rest-api-id 42ku123id8u3a --resource-id core-api-dev --http-method DELETE --type AWS --integration-http-method POST --uri 'arn:aws:lambda:us-east-1:my-lambda-function-arn' --region us-east-1
But it produces error message like this
An error occurred (NotFoundException) when calling the PutIntegration operation: Invalid Resource identifier specified
Is it possible to integrate api gateway method with existing lambda function using aws client? What is Resource identifier?
you can run aws apigateway get-resources to get the resource-id
aws apigateway get-resources --rest-api-id 42ku123id8u3a --region us-east-1
It will return a JSon like
{
"items": [
{
"path": "/resource/xxx",
"resourceMethods": {
"POST": {}
},
"id": "_yourresourceid_",
"pathPart": "xxx",
"parentId": "ai5b02"
}
]
}
you can take the id from this JSon and use it on your command for aws apigateway put-integration
Ideally you should export as JSON in step 2 'with integration extensions'. In the console there are 3 options for export type, and the middle one will include the integrations and authorizers in the export. Then when you import you'll have the integrations already.