由于权限问题,无法从API Gateway调用简单的Lambda

时间:2019-07-19 18:43:33

标签: amazon-web-services aws-lambda amazon-cloudformation

我遇到了一个非常愚蠢的错误,我感到非常愚蠢:)经过多次尝试,我决定将问题减少到最低限度,看看我是否可以尝试找出我做错的事情。

以下是一个CloudFormation模板:

  • 创建根角色
  • 创建一个将CloudWatch和S3权限附加到角色的策略
  • 创建一个API网关
  • 创建GET方法
  • 创建POST方法
  • 在NodeJS中使用内联代码创建一个简单的Lambda
  • 为POST方法创建权限以允许执行Lambda。
  • 创建一个Stage和API帐户

一切正常,没有错误,但是当我尝试执行API Gateway POST来测试与Lambda的通信时,却出现了错误:

Fri Jul 19 18:31:41 UTC 2019 : Endpoint request body after transformations: 
Fri Jul 19 18:31:41 UTC 2019 : Sending request to https://lambda.us-<REGION>.amazonaws.com/2015-03-31/functions/arn:aws:lambda:<REGION>:<ACCOUNT_REMOVED>:function:FileUpload/invocations
Fri Jul 19 18:31:41 UTC 2019 : Execution failed due to configuration error: Invalid permissions on Lambda function
Fri Jul 19 18:31:41 UTC 2019 : Method completed with status: 500

我已经阅读了许多教程,AWS参考资料,并与已经作为示例运行的其他API网关进行了比较,但是没有骰子,我做的事情很愚蠢,也许有人可以在我的CloudFormation模板中发现它。 / p>

非常感谢您

{
    "AWSTemplateFormatVersion": "2010-09-09",
    "Description": "AWS CloudFormation Template to create file server",
    "Parameters": {
        "Environment": {
            "Description": "Environment name",
            "Type": "String",
            "Default": "dev",
            "AllowedValues" : ["dev", "int", "stg", "prd"],
            "ConstraintDescription": "must be dev, int, stg or prd"
        },
        "deploymentVersion": {
            "Description": "Version of the lambda code",
            "Type": "String"
        }
    },
    "Resources": {
        "RootRole": {
            "Type": "AWS::IAM::Role",
            "Properties": {
                "RoleName": {"Fn::Join": ["", ["kepler-", {"Ref": "Environment"} ,"-keplerfiles-rootrole"]]},
                "AssumeRolePolicyDocument": {
                    "Version" : "2012-10-17",
                    "Statement": [ {
                        "Effect": "Allow",
                        "Principal": {
                            "Service": [ "apigateway.amazonaws.com", "lambda.amazonaws.com" ]
                        },
                        "Action": [ "sts:AssumeRole" ]
                    } ]
                }
            }
        },
        "RolePolicies": {
            "Type": "AWS::IAM::Policy",
            "Properties": {
                "PolicyName": {"Fn::Join": ["", ["kepler-", {"Ref": "Environment"} ,"-keplerfiles-rootpolicy"]]},
                "PolicyDocument": {
                   "Version" : "2012-10-17",
                   "Statement": [ {
                      "Effect": "Allow",
                      "Action": [
                        "logs:CreateLogGroup",
                        "logs:CreateLogStream",
                        "logs:PutLogEvents",
                        "s3:*"
                        ],
                      "Resource": "*"
                    } ]
                },
                "Roles": [ { "Ref": "RootRole" } ]
            }
        },
        "FilesRestApi": {
            "Type": "AWS::ApiGateway::RestApi",
            "Properties": {
                "Name" : "Kepler-FileServer-Next",
                "Description" : "API used for uploading and downloading files from S3",
                "FailOnWarnings" : true
            }
        },
        "RootFileResource": {
            "Type": "AWS::ApiGateway::Resource",
            "Properties": {
                "RestApiId": {"Ref": "FilesRestApi"},
                "ParentId": {"Fn::GetAtt": ["FilesRestApi", "RootResourceId"]},
                "PathPart": "keplerfiles2"
            }
        },
        "FolderResource": {
            "Type": "AWS::ApiGateway::Resource",
            "Properties": {
                "RestApiId": {"Ref": "FilesRestApi"},
                "ParentId": {"Ref": "RootFileResource"},
                "PathPart": "{folder}"
            }
        },
        "ItemResource": {
            "Type": "AWS::ApiGateway::Resource",
            "Properties": {
                "RestApiId": {"Ref": "FilesRestApi"},
                "ParentId": {"Ref": "FolderResource"},
                "PathPart": "{item}"
            }
        },
        "FileGetMethod": {
            "Type": "AWS::ApiGateway::Method",
            "Properties": {
                "AuthorizationType": "NONE",
                "HttpMethod": "GET",
                "RequestParameters" : {
                    "method.request.path.item": false,
                    "method.request.path.folder": false
                },
                "Integration": {
                    "Credentials" : {"Fn::GetAtt": ["RootRole", "Arn"]},
                    "Type": "AWS",
                    "IntegrationHttpMethod": "GET",
                    "PassthroughBehavior": "WHEN_NO_MATCH",
                    "RequestParameters" : {
                        "integration.request.path.object": "method.request.path.item",
                        "integration.request.header.x-amz-acl": "'authenticated-read'",
                        "integration.request.path.bucket": "method.request.path.folder"
                    },
                    "Uri": {"Fn::Join" : ["",
                        ["arn:aws:apigateway:", {"Ref": "AWS::Region"}, ":s3:path/{bucket}/{object}"]
                    ]},
                    "IntegrationResponses": [
                        {
                            "StatusCode": 500
                        },
                        {
                            "ResponseTemplates": {
                                "text/csv": "$input.body"
                            },
                            "SelectionPattern" : "2\\d{2}",
                            "StatusCode" : 200
                        }
                    ]
                },
                "ResourceId": {"Ref": "ItemResource"},
                "RestApiId": {"Ref": "FilesRestApi"},
                "MethodResponses": [
                    {
                        "ResponseModels": {
                            "text/csv": "Empty"
                        },
                        "StatusCode": 200
                    },
                    {
                        "StatusCode": 400
                    }
                ]
            }
        },
        "FilePostMethod": {
            "DependsOn": "FilePostPermission",
            "Type": "AWS::ApiGateway::Method",
            "Properties": {
                "AuthorizationType": "NONE",
                "HttpMethod": "POST",
                "Integration": {
                    "Credentials" : {"Fn::GetAtt": ["RootRole", "Arn"]},
                    "Type": "AWS",
                    "IntegrationHttpMethod": "POST",
                    "Uri": {"Fn::Join" : ["",
                        ["arn:aws:apigateway:", {"Ref": "AWS::Region"}, ":lambda:path/2015-03-31/functions/", {"Fn::GetAtt": ["SaveFileLambda", "Arn"]}, "/invocations"]
                    ]},
                    "IntegrationResponses": [
                        {
                            "StatusCode": 200
                        }
                    ]
                },
                "ResourceId": {"Ref": "RootFileResource"},
                "RestApiId": {"Ref": "FilesRestApi"},
                "MethodResponses": [
                    {
                        "StatusCode": 200
                    },
                    {
                        "StatusCode": 400
                    }
                ]
            }
        },
        "FilePostPermission": {
            "Type": "AWS::Lambda::Permission",
            "Properties": {
                "Action": "lambda:InvokeFunction",
                "FunctionName": {"Fn::GetAtt": ["SaveFileLambda", "Arn"]},
                "Principal": "apigateway.amazonaws.com",
                "SourceArn": {"Fn::Join": ["", [
                    "arn:aws:execute-api:",
                    {"Ref": "AWS::Region"}, ":",
                    {"Ref": "AWS::AccountId"}, ":",
                    {"Ref": "FilesRestApi"},
                    "/*"]
                ]}
            }
        },
        "SaveFileLambda": {
            "Type": "AWS::Lambda::Function",
            "Properties": {
                "FunctionName" : "FileUpload",
                "Description" : "Save file to S3",
                "Handler": "index.handler",
                "Role": { "Fn::GetAtt" : ["RootRole", "Arn"] },
                "Code": {
                    "ZipFile": {
                        "Fn::Join": [
                            "\n",
                            [
                                "exports.handler = function(event, context) {",
                                "  return { statusCode: 200, headers: { \"Content-Type\": \"text/html\" }, body: \"hello world!\" };",
                                "};"
                            ]
                        ]
                    }
                },
                "Runtime": "nodejs8.10",
                "Environment" : {
                    "Variables" : {
                        "DATABASE_REGION":{"Ref": "AWS::Region"}
                    }
                }
            }
        },
        "ApiGatewayCloudWatchLogsRole": {
            "Type": "AWS::IAM::Role",
            "Properties": {
                "AssumeRolePolicyDocument": {
                    "Version": "2012-10-17",
                    "Statement": [{
                        "Effect": "Allow",
                        "Principal": { "Service": ["apigateway.amazonaws.com"] },
                        "Action": ["sts:AssumeRole"]
                    }]
                },
                "Policies": [{
                    "PolicyName": "ApiGatewayLogsPolicy",
                    "PolicyDocument": {
                        "Version": "2012-10-17",
                        "Statement": [{
                            "Effect": "Allow",
                            "Action": [
                                "logs:CreateLogGroup",
                                "logs:CreateLogStream",
                                "logs:DescribeLogGroups",
                                "logs:DescribeLogStreams",
                                "logs:PutLogEvents",
                                "logs:GetLogEvents",
                                "logs:FilterLogEvents"
                            ],
                            "Resource": "*"
                        }]
                    }
                }]
            }
        },
        "ApiGatewayAccount": {
            "Type" : "AWS::ApiGateway::Account",
            "Properties" : {
                "CloudWatchRoleArn" : {"Fn::GetAtt" : ["ApiGatewayCloudWatchLogsRole", "Arn"] }
            }
        },
        "ApiDeployment": {
            "Type": "AWS::ApiGateway::Deployment",
            "DependsOn": ["FileGetMethod","FilePostMethod"],
            "Properties": {
                "RestApiId": {"Ref": "FilesRestApi"},
                "StageName": "cfstage"
            }
        },
        "ApiStage": {
            "DependsOn" : ["ApiGatewayAccount"],
            "Type": "AWS::ApiGateway::Stage",
            "Properties": {
                "DeploymentId": {"Ref": "ApiDeployment"},
                "MethodSettings": [{
                    "DataTraceEnabled": true,
                    "HttpMethod": "*",
                    "LoggingLevel": "INFO",
                    "ResourcePath": "/*"
                }],
                "RestApiId": {"Ref": "FilesRestApi"},
                "StageName": "v1"
            }
        }
    }
}

1 个答案:

答案 0 :(得分:1)

您看到的问题来自于设置集成角色以及Lambda权限。

因此,如果您从方法中删除执行角色并仅保留权限对象,那么您会很好的:

"FilePostMethod": {
    "DependsOn": "FilePostPermission",
    "Type": "AWS::ApiGateway::Method",
    "Properties": {
        "AuthorizationType": "NONE",
        "HttpMethod": "POST",
        "Integration": {
            "Type": "AWS",
            "IntegrationHttpMethod": "POST",
            "Uri": {"Fn::Join" : ["",
                ["arn:aws:apigateway:", {"Ref": "AWS::Region"}, ":lambda:path/2015-03-31/functions/", {"Fn::GetAtt": ["SaveFileLambda", "Arn"]}, "/invocations"]
            ]},
            "IntegrationResponses": [
                {
                    "StatusCode": 200
                }
            ]
        },
        "ResourceId": {"Ref": "RootFileResource"},
        "RestApiId": {"Ref": "FilesRestApi"},
        "MethodResponses": [
            {
                "StatusCode": 200
            },
            {
                "StatusCode": 400
            }
        ]
    }
},

或者,您可以删除该权限并将lambda:InvokeFunction权限添加到执行角色。