J'ai une ressource API Gateway qui exécute une fonction lambda. J'appelle la ressource API Gateway à l'aide du kit AWS Generated SDK de ma passerelle Api.
Voici la partie de la trace de pile de mon client qui semble pertinente:
Caused by: com.amazonaws.mobileconnectors.apigateway.ApiClientException: {"message": "Internal server error"} (Service: DevnetcountableClient; Status Code: 500; Error Code: null; Request ID: 348e8f98-6f55-11e6-97f6-098c2caf220f)
at com.amazonaws.mobileconnectors.apigateway.ApiClientHandler.handleResponse(ApiClientHandler.Java:255) at com.amazonaws.mobileconnectors.apigateway.ApiClientHandler.invoke(ApiClientHandler.Java:88)
at Java.lang.reflect.Proxy.invoke(Proxy.Java:393)
at $Proxy1.accountCreatePost(Unknown Source)
En regardant maintenant la console AWS, dans mon tableau de bord Api Gateway, je vois les demandes arriver et aboutir à "AWS/ApiGateway 5XXError". Cependant, il y a 0 journaux (que je peux trouver). Ma fonction lambda ne semble PAS être appelée et aucun journal lambda n'est affiché.
Voici à quoi ressemble mon lambda:
module.exports.createAccount = function(event, context, cb) {
console.log('createAccount');
console.log(event);
console.log(context);
console.log(cb);
cb(null, {status: 'SUCCESS', message: 'I ran!'});
};
Que puis-je faire pour déboguer cela?
Edit: D'accord, voici le script cloudformation qui regroupe tout.
{
"AWSTemplateFormatVersion":"2010-09-09",
"Description":"The AWS CloudFormation template for this Serverless application",
"Resources":{
"ServerlessDeploymentBucket":{
"Type":"AWS::S3::Bucket"
},
"IamRoleLambda":{
"Type":"AWS::IAM::Role",
"Properties":{
"AssumeRolePolicyDocument":{
"Version":"2012-10-17",
"Statement":[
{
"Effect":"Allow",
"Principal":{
"Service":[
"lambda.amazonaws.com"
]
},
"Action":[
"sts:AssumeRole"
]
}
]
},
"Path":"/"
}
},
"IamPolicyLambda":{
"Type":"AWS::IAM::Policy",
"Properties":{
"PolicyName":"dev-coolsoftware-lambda",
"PolicyDocument":{
"Version":"2012-10-17",
"Statement":[
{
"Effect":"Allow",
"Action":[
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource":"arn:aws:logs:us-west-2:*:*"
}
]
},
"Roles":[
{
"Ref":"IamRoleLambda"
}
]
}
},
"createAccount":{
"Type":"AWS::Lambda::Function",
"Properties":{
"Code":{
"S3Bucket":{
"Ref":"ServerlessDeploymentBucket"
},
"S3Key":"coolsoftware-1472853507538.Zip"
},
"FunctionName":"coolsoftware-dev-createAccount",
"Handler":"handler.createAccount",
"MemorySize":128,
"Role":{
"Fn::GetAtt":[
"IamRoleLambda",
"Arn"
]
},
"Runtime":"nodejs4.3",
"Timeout":30
}
},
"RestApiApigEvent":{
"Type":"AWS::ApiGateway::RestApi",
"Properties":{
"Name":"dev-coolsoftware"
}
},
"ResourceApigEventCreateaccountAccount":{
"Type":"AWS::ApiGateway::Resource",
"Properties":{
"ParentId":{
"Fn::GetAtt":[
"RestApiApigEvent",
"RootResourceId"
]
},
"PathPart":"account",
"RestApiId":{
"Ref":"RestApiApigEvent"
}
}
},
"PutMethodApigEventCreateaccountAccount":{
"Type":"AWS::ApiGateway::Method",
"Properties":{
"AuthorizationType":"AWS_IAM",
"HttpMethod":"PUT",
"MethodResponses":[
{
"ResponseModels":{
"application/json":"AccountCreationResponseModel"
},
"ResponseParameters":{
},
"StatusCode":"200"
}
],
"RequestParameters":{
},
"Integration":{
"IntegrationHttpMethod":"POST",
"Type":"AWS",
"Uri":{
"Fn::Join":[
"",
[
"arn:aws:apigateway:",
{
"Ref":"AWS::Region"
},
":lambda:path/2015-03-31/functions/",
{
"Fn::GetAtt":[
"createAccount",
"Arn"
]
},
"/invocations"
]
]
},
"RequestTemplates":{
"application/json":"\n #define( $loop )\n {\n #foreach($key in $map.keySet())\n \"$util.escapeJavaScript($key)\":\n \"$util.escapeJavaScript($map.get($key))\"\n #if( $foreach.hasNext ) , #end\n #end\n }\n #end\n {\n \"body\": $input.json(\"$\"),\n \"method\": \"$context.httpMethod\",\n \"principalId\": \"$context.authorizer.principalId\",\n \"stage\": \"$context.stage\",\n\n #set( $map = $input.params().header )\n \"headers\": $loop,\n\n #set( $map = $input.params().querystring )\n \"query\": $loop,\n\n #set( $map = $input.params().path )\n \"path\": $loop,\n\n #set( $map = $context.identity )\n \"identity\": $loop,\n\n #set( $map = $stageVariables )\n \"stageVariables\": $loop\n }\n "
},
"IntegrationResponses":[
{
"StatusCode":"200",
"ResponseParameters":{
},
"ResponseTemplates":{
"application/json":""
}
}
]
},
"ResourceId":{
"Ref":"ResourceApigEventCreateaccountAccount"
},
"RestApiId":{
"Ref":"RestApiApigEvent"
},
"RequestModels":{
"application/json":"AccountCreationRequestModel"
}
}
},
"DeploymentApigEvent1472853508283":{
"Type":"AWS::ApiGateway::Deployment",
"Properties":{
"RestApiId":{
"Ref":"RestApiApigEvent"
},
"StageName":"dev"
},
"DependsOn":[
"PutMethodApigEventCreateaccountAccount"
]
},
"createAccountApigPermission":{
"Type":"AWS::Lambda::Permission",
"Properties":{
"FunctionName":{
"Fn::GetAtt":[
"createAccount",
"Arn"
]
},
"Action":"lambda:InvokeFunction",
"Principal":"apigateway.amazonaws.com"
}
},
"DynamoDBTableAccounts":{
"Type":"AWS::DynamoDB::Table",
"DeletionPolicy":"Retain",
"Properties":{
"TableName":"dev-coolsoftware-accounts",
"ProvisionedThroughput":{
"ReadCapacityUnits":1,
"WriteCapacityUnits":1
},
"AttributeDefinitions":[
{
"AttributeName":"accountid",
"AttributeType":"S"
}
],
"KeySchema":[
{
"AttributeName":"accountid",
"KeyType":"HASH"
}
]
}
},
"AccountCreationRequestModel":{
"Type":"AWS::ApiGateway::Model",
"Properties":{
"RestApiId":{
"Ref":"RestApiApigEvent"
},
"ContentType":"application/json",
"Description":"Schema for AccountCreationRequestModel",
"Name":"AccountCreationRequestModel",
"Schema":{
"$schema":"http://json-schema.org/draft-04/schema#",
"title":"AccountCreationRequestModel",
"type":"object",
"properties":{
"publickey":{
"type":"string"
},
"deviceid":{
"type":"string"
}
}
}
}
},
"AccountCreationResponseModel":{
"Type":"AWS::ApiGateway::Model",
"Properties":{
"RestApiId":{
"Ref":"RestApiApigEvent"
},
"ContentType":"application/json",
"Description":"Schema for AccountCreationResponseModel",
"Name":"AccountCreationResponseModel",
"Schema":{
"$schema":"http://json-schema.org/draft-04/schema#",
"title":"AccountCreationResponseModel",
"type":"object",
"properties":{
"status":{
"type":"string"
},
"message":{
"type":"string"
}
}
}
}
},
"FailureResponseModel":{
"Type":"AWS::ApiGateway::Model",
"Properties":{
"RestApiId":{
"Ref":"RestApiApigEvent"
},
"ContentType":"application/json",
"Description":"Schema for FailureResponseModel",
"Name":"FailureResponseModel",
"Schema":{
"$schema":"http://json-schema.org/draft-04/schema#",
"title":"FailureResponseModel",
"type":"object",
"properties":{
"status":{
"type":"string"
},
"message":{
"type":"string"
}
}
}
}
}
},
"Outputs":{
"ServerlessDeploymentBucketName":{
"Value":{
"Ref":"ServerlessDeploymentBucket"
}
},
"Function1Arn":{
"Description":"Lambda function info",
"Value":{
"Fn::GetAtt":[
"createAccount",
"Arn"
]
}
},
"ServiceEndpoint":{
"Description":"URL of the service endpoint",
"Value":{
"Fn::Join":[
"",
[
"https://",
{
"Ref":"RestApiApigEvent"
},
".execute-api.us-west-2.amazonaws.com/dev"
]
]
}
}
}
}
Edit 2: Lorsque je teste le point de terminaison à l'aide de la fonctionnalité de test d'API Gateway dans la console AWS, tout fonctionne très bien: /
Edit 3: Mise à jour du script cloudformation - ne fonctionne toujours pas.
Comment déboguer:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:DescribeLogGroups",
"logs:DescribeLogStreams",
"logs:PutLogEvents",
"logs:GetLogEvents",
"logs:FilterLogEvents"
],
"Resource": "*"
}
]
}
Avec la politique de confiance suivante:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": "apigateway.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
Dans la console API Gateway pour la région de votre API: Accédez aux paramètres >>> Entrez l'ARN du rôle de journalisation API Gateway-CloudWatch >>> cliquez sur 'Enregistrer'
Passez à l'étape de votre API. Sous "Paramètres CloudWatch", sélectionnez "Activer les journaux CloudWatch". Réglez 'Log level' sur 'INFO'. Sélectionnez "Consigner les données complètes des demandes/réponses".
Redéployez votre API à cette étape: accédez à l'onglet "Ressources" de votre API. Sélectionnez Actions >>> Déployer l'API.
Faites des demandes, attendez quelques minutes et voyez ce que disent les journaux (dans CloudWatch).
L'erreur:
La cause:
Une fois que j'ai activé "Appeler avec les informations d'identification de l'appelant" en utilisant Credentials: 'arn:aws:iam::*:user/*'
, le rôle IAM de l'appelant n'avait pas accès pour appeler la fonction lambda. Cela a entraîné l'erreur 500. Une fois que j'ai donné l'accès au rôle IAM de l'appelant, tout a commencé à fonctionner correctement.
Que montre le journal API Gateway? affiche-t-il "Autorisations non valides sur la fonction Lambda"? Je pense que vous devrez inclure la création d'autorisation (ressource) dans le modèle CloudFormation. Voici l'un des miens:
"PERMISSIONGET": {
"Type": "AWS::Lambda::Permission",
"Properties": {
"FunctionName": "createCabinet",
"Action": "lambda:InvokeFunction",
"Principal": "apigateway.amazonaws.com",
"SourceArn": {
"Fn::Join": [
"",
[
"arn:aws:execute-api:us-east-1:87875636623:",
{
"Ref": "APIGATEWAY"
},
"/*/GET/*"
]
]
}
},
"DependsOn": "APIDEPLOYMENT"
}
Au cas où quelqu'un en aurait besoin.
Le lien suivant explique comment activer les journaux cloudwatch pour le débogage des problèmes de passerelle api.
https://kennbrodhagen.net/2016/07/23/how-to-enable-logging-for-api-gateway/