通过cloudformation

时间:2018-04-30 15:30:15

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

我正在尝试使用cloudformation创建一个通过代理指向lambda的api网关:

首先,我创建我的root并授予它权限:

  RestApiHamed:
   Type: 'AWS::ApiGateway::RestApi'
   Properties:
   Name: hamed-proxy-test
  APIGatewayToLambdaPermission:
   Type: AWS::Lambda::Permission
   DependsOn: RestApiHamed
   Properties:
     Action: lambda:invokeFunction
     FunctionName: test-stg1-lambda-product-get
     Principal: apigateway.amazonaws.com
     SourceArn: #!Sub "arn:aws:execute- 
      api:${AWS::Region}:${AWS::AccountId}:RestApiHamed/*"
      Fn::Join:
      - ''
      - - 'arn:aws:execute-api:'
        - Ref: AWS::Region
        - ":"
        - Ref: AWS::AccountId
        - ":"
        - Ref: RestApiHamed
        - "/*"

然后我创建我的方法:

  ChannelsStoriesGetMethod:
   Type: AWS::ApiGateway::Method
   DependsOn: APIGatewayToLambdaPermission
   Properties:
     AuthorizationType: NONE
     HttpMethod: GET
     Integration:
       Type: HTTP
       IntegrationHttpMethod: GET
       IntegrationResponses:
        -
          StatusCode: 200
       Type: AWS_PROXY
       Uri: !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:048947288163:function:zuora-stg1-lambda-product-get/invocations
    ResourceId: !Ref ChannelsStoriesPath
    RestApiId:
      Ref: RestApiHamed
    MethodResponses:
    - StatusCode: 200
      ResponseParameters:
        method.response.header.Access-Control-Allow-Origin: true

现在,当我运行cloudformation时,它成功了,我可以看到我的网关但是当我尝试网关时,我得到了:

 <Message>Unable to determine service/operation name to be 
  authorized</Message>
</AccessDeniedException>
 Execution failed due to configuration error: Malformed Lambda proxy response

但是一旦我转到集成请求并在lambda函数中编辑clcik然后我点击保存我会弹出一个请求权限附件,当我接受它然后它开始工作。问题是什么? 我确实在我的cfn代码中添加了权限,我希望你可以看到这件作品。我应该添加其他东西吗?

完整的cfn代码如下:

{
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "API gateway for TJ services",
"Parameters": {
    "BusinessUnit": {
        "Description": "BusinessUnit",
        "Type": "String",
        "ConstraintDescription": "Any string"
    },
    "project": {
        "Description": "project",
        "Type": "String",
        "ConstraintDescription": "Any string"
    },
    "EnvironmentApp": {
        "Description": "EnvironmentApp",
        "Type": "String",
        "ConstraintDescription": "Any string"
    },
    "EnvironmentInfra": {
        "Description": "EnvironmentInfra",
        "Type": "String",
        "ConstraintDescription": "Any string"
    }
},
"Resources": {
    "LambdaHelloworldRole": {
        "Type": "AWS::IAM::Role",
        "Properties": {
            "RoleName": "${project}-${EnvironmentApp}-lambda-helloworld",
            "AssumeRolePolicyDocument": {
                "Version": "2012-10-17",
                "Statement": [{
                    "Effect": "Allow",
                    "Principal": {
                        "Service": [
                            "lambda.amazonaws.com",
                            "apigateway.amazonaws.com"
                        ]
                    },
                    "Action": [
                        "sts:AssumeRole"
                    ]
                }]
            },
            "Path": "/",
            "Policies": [{
                "PolicyName": "${project}-${EnvironmentApp}-lambda-helloworld",
                "PolicyDocument": {
                    "Version": "2012-10-17",
                    "Statement": [{
                        "Effect": "Allow",
                        "Action": [
                            "logs:CreateLogGroup",
                            "logs:CreateLogStream",
                            "logs:PutLogEvents",
                            "logs:DescribeLogGroups",
                            "logs:DescribeLogStreams",
                            "logs:PutLogEvents",
                            "logs:GetLogEvents",
                            "logs:FilterLogEvents"
                        ],
                        "Resource": "*"
                    }]
                }
            }]
        }
    },
    "LambdaHelloworld": {
        "Type": "AWS::Lambda::Function",
        "Properties": {
            "Handler": "index.lambda_handler",
            "Timeout": 180,
            "MemorySize": 1536,
            "Environment": {
                "Variables": {
                    "test": "test"
                }
            },
            "FunctionName": "${project}-${EnvironmentApp}-lambda-helloworld-pipeline-test",
            "Role": {
                "Fn::GetAtt": [
                    "LambdaHelloworldRole",
                    "Arn"
                ]
            },
            "Code": {
                "ZipFile": {
                    "Fn::Join": [
                        "\n", [
                            "import boto3",
                            "import http.client",
                            "import json",
                            "import urllib.request",
                            "import urllib.parse",
                            "import sys",
                            "def lambda_handler(event, context):",
                            "   return { 'statusCode': 200, 'headers': { 'Access-Control-Allow-Origin': '*' }, 'body': 'hello world stg2'}"
                        ]
                    ]
                }
            },
            "Runtime": "python3.6"
        }
    },
    "RestApiHellowworld": {
        "Type": "AWS::ApiGateway::RestApi",
        "Properties": {
            "Name": "hamed-proxy-test"
        }
    },
    "APIGatewayToLambdaPermission": {
        "Type": "AWS::Lambda::Permission",
        "DependsOn": "RestApiHellowworld",
        "Properties": {
            "Action": "lambda:invokeFunction",
            "FunctionName": "zuora-stg1-lambda-product-get",
            "Principal": "apigateway.amazonaws.com"
        }
    },
    "ChannelsStoriesPath": {
        "Type": "AWS::ApiGateway::Resource",
        "Properties": {
            "RestApiId": {
                "Ref": "RestApiHellowworld"
            },
            "ParentId": {
                "Fn::GetAtt": [
                    "RestApiHellowworld",
                    "RootResourceId"
                ]
            },
            "PathPart": "stories"
        }
    },
    "ChannelsStoriesOptionsMethod": {
        "Type": "AWS::ApiGateway::Method",
        "Properties": {
            "AuthorizationType": "NONE",
            "RestApiId": {
                "Ref": "RestApiHellowworld"
            },
            "ResourceId": "ChannelsStoriesPath",
            "HttpMethod": "OPTIONS",
            "Integration": {
                "IntegrationResponses": [{
                    "StatusCode": 200,
                    "ResponseParameters": {
                        "method.response.header.Access-Control-Allow-Headers": "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'",
                        "method.response.header.Access-Control-Allow-Methods": "'POST,OPTIONS,GET,PUT'",
                        "method.response.header.Access-Control-Allow-Origin": "'*'"
                    },
                    "ResponseTemplates": {
                        "application/json": ""
                    }
                }],
                "PassthroughBehavior": "WHEN_NO_MATCH",
                "RequestTemplates": {
                    "application/json": "{\"statusCode\": 200}"
                },
                "Type": "MOCK"
            },
            "MethodResponses": [{
                "StatusCode": 200,
                "ResponseModels": {
                    "application/json": "Empty"
                },
                "ResponseParameters": {
                    "method.response.header.Access-Control-Allow-Headers": true,
                    "method.response.header.Access-Control-Allow-Methods": true,
                    "method.response.header.Access-Control-Allow-Origin": true
                }
            }]
        }
    },
    "ChannelsStoriesGetMethod": {
        "Type": "AWS::ApiGateway::Method",
        "DependsOn": [
            "APIGatewayToLambdaPermission",
            "LambdaHelloworld"
        ],
        "Properties": {
            "AuthorizationType": "NONE",
            "HttpMethod": "GET",
            "Integration": {
                "Type": "AWS_PROXY",
                "IntegrationHttpMethod": "GET",
                "IntegrationResponses": [{
                    "StatusCode": 200,
                    "ResponseParameters": {
                        "method.response.header.Access-Control-Allow-Origin": "'*'"
                    }
                }],
                "Uri": {
                    "Fn::Join": [
                        "", [
                            "arn:aws:apigateway:",
                            {
                                "Ref": "AWS::Region"
                            },
                            ":",
                            "lambda:path/2015-03-31/functions/",
                            "arn:aws:lambda:us-east-1:048947288163:function:${project}-",
                            "${stageVariables.stg}-lambda-helloworld-pipeline-test",
                            "/invocations"
                        ]
                    ]
                }
            },
            "ResourceId": "ChannelsStoriesPath",
            "RestApiId": {
                "Ref": "RestApiHellowworld"
            },
            "MethodResponses": [{
                "StatusCode": 200
            }]
        }
    },
    "ApiGatewayEventLogGroup": {
        "Type": "AWS::Logs::LogGroup",
        "Properties": {
            "LogGroupName": {
                "Fn::Join": [
                    "", [
                        "/aws/apigateway/",
                        "${project}-${EnvironmentApp}-helloworld"
                    ]
                ]
            },
            "RetentionInDays": 1
        }
    },
    "ApiGatewayEventLogStream": {
        "Type": "AWS::Logs::LogStream",
        "Properties": {
            "LogGroupName": {
                "Ref": "ApiGatewayEventLogGroup"
            },
            "LogStreamName": "${project}-${EnvironmentApp}-helloworld"
        },
        "DependsOn": [
            "ApiGatewayEventLogGroup"
        ]
    },
    "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:*"
                        ],
                        "Resource": [
                            [
                                "ApiGatewayEventLogGroup",
                                "Arn"
                            ],
                            "*"
                        ]
                    }]
                }
            }]
        }
    },
    "ApiGatewayAccount": {
        "Type": "AWS::ApiGateway::Account",
        "DependsOn": "ApiGatewayCloudWatchLogsRole",
        "Properties": {
            "CloudWatchRoleArn": {
                "Fn::GetAtt": [
                    "ApiGatewayCloudWatchLogsRole",
                    "Arn"
                ]
            }
        }
    },
    "ApiDeployment": {
        "Type": "AWS::ApiGateway::Deployment",
        "DependsOn": "ChannelsStoriesGetMethod",
        "Properties": {
            "RestApiId": {
                "Ref": "RestApiHellowworld"
            }
        }
    },
    "ApiStage": {
        "DependsOn": [
            "ApiGatewayAccount"
        ],
        "Type": "AWS::ApiGateway::Stage",
        "Properties": {
            "DeploymentId": {
                "Ref": "ApiDeployment"
            },
            "MethodSettings": [{
                "DataTraceEnabled": true,
                "HttpMethod": "*",
                "LoggingLevel": "INFO",
                "ResourcePath": "/*"
            }],
            "RestApiId": {
                "Ref": "RestApiHellowworld"
            },
            "StageName": "${EnvironmentApp}",
            "Variables": {
                "stg": "${EnvironmentApp}"
            }
        }
    }
},
"Outputs": {
    "RootResourceId": {
        "Description": "Tj Services Rest API root resource id",
        "Value": "RestApiHellowworld.RootResourceId",
        "Export": {
            "Name": "${project}-${EnvironmentApp}-RootResourceId-helloworld"
        }
    },
    "RestTjApi": {
        "Description": "Tj Services Rest API",
        "Value": "RestApiHellowworld",
        "Export": {
            "Name": "${project}-restApi-tj-services-helloworld"
        }
    }
}

}

1 个答案:

答案 0 :(得分:2)

我不认为您的cloudformation脚本能够向API网关添加调用lambda函数权限。我宁愿以下列方式实现这个目标

APIName:
 Type: "AWS::ApiGateway::RestApi"
 Properties:
  Description: "Description"
  Name: "APIName"
  FailOnWarnings: true

APILambdaPermission:
 Type: "AWS::Lambda::Permission"
 Properties:
  Action: "lambda:InvokeFunction"
  FunctionName: !Ref LambdaFunctionName
  Principal: "apigateway.amazonaws.com"


LambdaFunctionName:
 Type: "AWS::Serverless::Function"
 Properties:
  Handler: index.handler
  Runtime: nodejs6.10
  CodeUri: s3://codeBucketName/index.zip
  Role: !GetAtt RoleName.Arn

RoleName:
 Type: AWS::IAM::Role
 Properties:
  AssumeRolePolicyDocument:
    Version: 2012-10-17
    Statement:
      - Effect: Allow
        Principal:
          Service: lambda.amazonaws.com
        Action: sts:AssumeRole
  ManagedPolicyArns:
    - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole