amazon-web-services - start - serverless yml runtime
¿Cómo depuro AWS Api Gateway & Lambda "AWS/ApiGateway 5XXError"? (3)
Tengo un recurso de puerta de enlace API que ejecuta una función lambda. Estoy llamando al recurso API Gateway utilizando el SDK generado por AWS desde mi Api Gateway.
Aquí está la parte del stacktrace de mi cliente que parece relevante:
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)
Ahora, mirando la consola de AWS, dentro de mi panel de control de la puerta de enlace de Api veo las solicitudes que llegan y dan como resultado "AWS / ApiGateway 5XXError". Sin embargo hay 0 registros (que puedo encontrar). Mi función lambda NO parece ser llamada, y no se muestran los registros lambda.
En este momento, así es como se ve mi 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!''});
};
¿Qué puedo hacer para depurar esto?
Edición: Bueno, aquí está el script de formación de nube que está juntando todo.
{
"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"
]
]
}
}
}
}
Edición 2: cuando pruebo el punto final utilizando la función de prueba de la puerta de enlace API en la consola de AWS, todo funciona muy bien: /
Edición 3: se actualizó nuevamente la secuencia de comandos de formación de nube, aún no funciona
¿Qué muestra el API Gateway Log? ¿Muestra "Permisos inválidos en la función Lambda"? Creo que deberás incluir la creación de permiso (recurso) en la plantilla de CloudFormation. Aquí esta uno de los míos:
"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"
}
En caso de que alguien lo necesite.
El siguiente enlace explica cómo habilitar los registros de cloudwatch para depurar problemas de la puerta de enlace de la API.
https://kennbrodhagen.net/2016/07/23/how-to-enable-logging-for-api-gateway/
Cómo depurar:
- Cree un rol de IAM para permitir que la puerta de enlace de la API envíe los registros a CloudWatch. El rol debe tener la siguiente política adjunta:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:DescribeLogGroups",
"logs:DescribeLogStreams",
"logs:PutLogEvents",
"logs:GetLogEvents",
"logs:FilterLogEvents"
],
"Resource": "*"
}
]
}
Con la siguiente política de confianza:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": "apigateway.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
En la consola de la puerta de enlace API para la región de su API: Vaya a configuración >>> Ingrese en el ARN de la función de registro API Gateway-CloudWatch >>> haga clic en ''Guardar''
Ve a la etapa de tu API. Bajo ''Configuración de CloudWatch'', seleccione ''Habilitar registros de CloudWatch''. Establezca ''Nivel de registro'' en ''INFO''. Seleccione ''Registrar datos completos de solicitudes / respuestas''.
Vuelva a implementar su API en esa etapa: vaya a la pestaña ''Recursos'' para su API. Seleccione Acciones >>> Implementar API.
Haga solicitudes, espere unos minutos y vea lo que dicen los registros (en CloudWatch).
El error:
La causa:
Una vez que habilité "Invocar con credenciales de llamante" usando Credentials: ''arn:aws:iam::*:user/*''
, el rol IAM del llamante no tuvo acceso para invocar la función lambda. Esto resultó en el error 500. Una vez que le di acceso a la función IAM de la persona que llama, todo comenzó a funcionar correctamente.