【问题标题】:Add permission for triggering lambda in api gateway via cloudformation通过 cloudformation 在 api 网关中添加触发 lambda 的权限
【发布时间】:2018-05-29 05:48:07
【问题描述】:

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

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

  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"
        }
    }
}

}

【问题讨论】:

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


    【解决方案1】:

    我认为您的 cloudformation 脚本无法将调用 lambda 函数权限添加到 API 网关。我宁愿通过以下方式实现这一目标

    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
    

    【讨论】:

    • 您好,感谢您的回答。 IU尝试了同样的结果。与您的代码和我的代码的唯一区别是 sourceArn 的权限对吗?
    • 是的,没错。我总是从我很久以前写的上面的 cloudformation 脚本中添加 lambda 调用权限。您的脚本和我的脚本之间的另一个区别是 Lambda 函数的创建。我允许 SAM 使用 S3 存储桶上的代码创建我的 Lambda 函数。我可以查看您的整个 cloudformation 脚本来帮助您解决错误吗?
    • 谢谢,当然我在帖子中添加了我的代码。抱歉,我必须将其转换为 json 才能添加。如果您能帮助我解决此问题,我将不胜感激
    • 要在 Lambda 函数上添加调用权限,您必须创建一个 Lmabda 函数作为此 cloudformation 脚本的一部分。您不能授予从该 cloudformation 脚本调用现有函数的权限。我建议您将 zip 文件中的代码上传到 S3 并创建该函数作为脚本的一部分。希望对你有帮助
    • 我想我正在这个 cfn 中创建函数:LambdaHelloworld。你是这个意思吗?
    猜你喜欢
    • 1970-01-01
    • 2017-08-20
    • 2017-02-15
    • 2020-01-08
    • 1970-01-01
    • 2018-10-03
    • 2020-01-29
    • 1970-01-01
    • 2019-01-30
    相关资源
    最近更新 更多