Lambda 调用权限与 API 网关权限冲突

Permissions for Lambda invocation conflicts with API Gateway permissions

我已将一个应用程序部署到 Lambda,我正在使用 API 网关将 HTTP 请求转发到该应用程序。

我的问题是 API 网关似乎没有转发不属于应用基础 URL 的请求。

换句话说,当有对 https://blabblahblah.execute-api.us-west-2.amazonaws.com/Prod/ 的 HTTP 请求时,我的 Lambda 处理程序中的代码就会执行。但是,对 https://blabblahblah.execute-api.us-west-2.amazonaws.com/Prod/pong 的 HTTP 请求会抛出 500,并且不会执行任何代码。我的处理程序中有一些日志记录语句,它们不会为非基本 URL 请求记录任何内容。

我已将问题缩小为权限问题。

我有 2 组权限不能很好地协同工作。

  1. 我需要允许 API 网关调用我的 lambda 函数
  2. lambda 函数需要能够调用自身。

我以为我的这两个权限都能正常工作,但是任何不针对基础 URL 的 HTTP 请求都会在 API 网关中抛出 500(即我看不到 Cloudwatch 日志条目对于请求,但响应是 500)。

我认为这意味着我的 SAM 模板中一定有错误。

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

  MyFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: lambda.handler
      Role: !GetAtt IAMRole.Arn
      Runtime: ruby2.5
      CodeUri: "./src/"
      MemorySize: 512
      Timeout: 30
      Events:
        MyAppApi:
            Type: Api
            Properties:
                Path: /
                Method: ANY
                RestApiId: !Ref MyAppAPI
  MyAppAPI:
    Type: AWS::Serverless::Api
    Properties:
      Name: MyAppAPI
      StageName: Prod
      DefinitionBody:
        swagger: '2.0'
        basePath: '/'
        info:
          title: !Ref AWS::StackName
        paths:
          /{proxy+}:
            x-amazon-apigateway-any-method:
              responses: {}
              x-amazon-apigateway-integration:
                uri:
                  !Sub 'arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${MyFunction.Arn}/invocations'
                passthroughBehavior: "when_no_match"
                httpMethod: POST
                type: "aws_proxy"
          /:
            post:
              responses: {}
              x-amazon-apigateway-integration:
                uri:
                  !Sub 'arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${MyFunction.Arn}/invocations'
                passthroughBehavior: "when_no_match"
                httpMethod: POST
                type: "aws_proxy"
  ConfigLambdaPermission:
    Type: "AWS::Lambda::Permission"
    DependsOn:
    - MyFunction
    Properties:
      Action: lambda:InvokeFunction
      FunctionName: !Ref MyFunction
      Principal: apigateway.amazonaws.com
  ConfigLambdaPermission:
    Type: "AWS::Lambda::Permission"
    DependsOn:
    - MyFunction
    Properties:
      Action: lambda:InvokeFunction
      FunctionName: !Ref MyFunction
      Principal: !GetAtt IAMRole.Arn

Outputs:
  MyFunction:
    Description: Lambda Function for interacting with Slack
    Value:
      Fn::GetAtt:
      - MyFunction
      - Arn
  MyAppAppUrl:
    Description: App endpoint URL
    Value: !Sub "https://${MyAppAPI}.execute-api.${AWS::Region}.amazonaws.com/"

知道如何让事情正常进行吗?

是的,您需要添加其他资源以及事件触发器。而且您的 lambda 权限在上述模板中没有用处。以下是它对我的作用。

AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Resources:
  IAMRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Action: ['sts:AssumeRole']
            Effect: Allow
            Principal:
              Service: [lambda.amazonaws.com]
        Version: 2012-10-17
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole

  MyFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: roleTest.roleTest
      Role: !GetAtt IAMRole.Arn
      Runtime: nodejs8.10
      CodeUri: s3://apicfn/roleTest.zip
      MemorySize: 512
      Timeout: 30
      Events:
        MyAppApi1:
            Type: Api
            Properties:
                Path: /
                Method: ANY
        MyAppApi2:
            Type: Api
            Properties:
                Path: /{proxy+}
                Method: ANY
Outputs:
  MyFunction:
    Description: Lambda Function for interacting with Slack
    Value:
      Fn::GetAtt:
      - MyFunction
      - Arn

PS:此模板甚至不需要 Serverless::Api 部分。