【问题标题】:Lambda permissions error when setup using CloudFormation and API Gateway proxy使用 CloudFormation 和 API Gateway 代理设置时出现 Lambda 权限错误
【发布时间】:2018-07-22 07:07:28
【问题描述】:

我正在尝试编写一个 cloudformation 脚本,该脚本将创建一个 lambda 函数并将其连接到 API Gateway 代理资源。堆栈创建工作,但权限或集成配置有问题,当我测试端点时,我不断收到

2018 年 2 月 12 日星期一 06:45:28 UTC:端点响应正文之前 转换:无法 确定要授权的服务/操作名称

2018 年 2 月 12 日星期一 06:45:28 UTC:端点响应标头: {连接=保持活动状态, x-amzn-RequestId=4fdf1e92-0fc0-11e8-b3f1-0134476f962c, 内容长度=130,日期=星期一,2018 年 2 月 12 日 06:45:28 GMT} 2 月 12 日星期一 06:45:28 UTC 2018:由于配置错误,执行失败: 2018 年 2 月 12 日星期一 06:45:28 UTC 格式错误的 Lambda 代理响应:方法 完成状态:502

这是我的 cloudformation 脚本:

AWSTemplateFormatVersion: 2010-09-09
Description: An API that proxies requests to another HTTP endpoint

Resources:
  MyFunction:
    Type: 'AWS::Lambda::Function'
    Properties:
      Handler: samplefunction.lambda_handler
      Runtime: python2.7
      Code:
        S3Bucket: "ilya-lambdas"
        S3Key: "lambda-code.zip"
      Role: 'arn:aws:iam::acc-id:role/service-role/basic_lambda_role'


  Api:
    Type: 'AWS::ApiGateway::RestApi'
    Properties:
      Name: foo3

  Resource:
    Type: 'AWS::ApiGateway::Resource'
    Properties:
      ParentId: !GetAtt Api.RootResourceId
      RestApiId: !Ref Api
      PathPart: 'test'


  RootMethod:
    Type: 'AWS::ApiGateway::Method'
    Properties:
      AuthorizationType: NONE
      HttpMethod: ANY
      ResourceId: !GetAtt Api.RootResourceId
      RestApiId: !Ref Api 
      Integration:
          IntegrationHttpMethod: ANY
          IntegrationResponses:
            - StatusCode: 200
              SelectionPattern: .*
          Type: AWS_PROXY
          PassthroughBehavior: WHEN_NO_MATCH
          Uri: !Join ["", ["arn:aws:apigateway:", "us-east-1", ":lambda:path/2015-03-31/functions/", !GetAtt MyFunction.Arn, "/invocations"] ]
          Credentials: 'arn:aws:iam::acc-id:role/service-role/basic_lambda_role'

  ProxyMethod:
      Type: 'AWS::ApiGateway::Method'
      Properties:
        HttpMethod: ANY
        ResourceId: !Ref Resource
        RestApiId: !Ref Api
        AuthorizationType: NONE
        Integration:
          IntegrationHttpMethod: ANY
          IntegrationResponses:
            - StatusCode: 200
              SelectionPattern: .*
          Type: AWS_PROXY
          Uri: !Join ["", ["arn:aws:apigateway:", "us-east-1", ":lambda:path/2015-03-31/functions/", !GetAtt MyFunction.Arn, "/invocations"] ]
          PassthroughBehavior: WHEN_NO_MATCH
          Credentials: 'arn:aws:iam::acc-id:role/service-role/basic_lambda_role'

  FunctionPermissions:
    Type: "AWS::Lambda::Permission"
    Properties: 
      Action: "lambda:InvokeFunction"        
      FunctionName: !GetAtt MyFunction.Arn
      Principal: "apigateway.amazonaws.com"
      SourceArn: !Join [ "", ["arn:aws:execute-api:", !Ref "AWS::Region", ":", !Ref "AWS::AccountId", ":", !Ref Api, "/*/*/*" ] ] 



  Deployment:
    DependsOn:
      - MyFunction
      - RootMethod
      - ProxyMethod
    Type: 'AWS::ApiGateway::Deployment'
    Properties:
      RestApiId: !Ref Api
      StageName: prod

我已经坚持了一段时间,任何指针将不胜感激。

【问题讨论】:

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


    【解决方案1】:

    首先,我注意到您的IntegrationHttpMethodANY。对于 Lambda,除非您使用 {proxy+} 配置,否则请尝试使用 POST。我很确定 CloudFormation 文档仍然过时,但您会在 this answer 中找到一些有用的信息。

    我注意到的第二件事是格式错误的代理响应,在您的情况下,这可能只是配置错误。为了排除这种情况,处理格式错误的代理响应是 AWS 支持中心上的 answered。基本上,您的 lambda 响应应采用以下格式,包括不添加任何额外的键。

    {
        "isBase64Encoded": true|false,
        "statusCode": httpStatusCode,
        "headers": { "headerName": "headerValue", ... },
        "body": "..."
    }
    

    您可以使用支持文档中的示例函数代替常规函数,以便隔离问题。

    【讨论】:

    • Miles,感谢您的回复,以及您关于将 IntegrationHttpMethod 从 ANY 更改为 POST 的建议。这清除了一个障碍。但是,这不是一个完整的解决方案,还有权限问题,如果您好奇,请参阅下面的答案。
    【解决方案2】:

    经过反复试验,结合 Miles 的建议,我得到了可以工作的 CloudFormation 脚本:

    AWSTemplateFormatVersion: 2010-09-09
    Description: An API that proxies requests to another HTTP endpoint
    
    Resources:
      MyFunction:
        Type: 'AWS::Lambda::Function'
        Properties:
          Handler: samplefunction.lambda_handler
          Runtime: python2.7
          Code:
            S3Bucket: "ilya-lambdas"
            S3Key: "lambda-code.zip"
          Role: !Join ["", ["arn:aws:iam::", !Ref "AWS::AccountId", ":role/service-role/basic_lambda_role"] ]
    
    
      Api:
        Type: 'AWS::ApiGateway::RestApi'
        Properties:
          Name: foo3
    
      Resource:
        Type: 'AWS::ApiGateway::Resource'
        Properties:
          ParentId: !GetAtt Api.RootResourceId
          RestApiId: !Ref Api
          PathPart: 'test'
    
    
      RootMethod:
        Type: 'AWS::ApiGateway::Method'
        Properties:
          AuthorizationType: NONE
          HttpMethod: ANY
          ResourceId: !GetAtt Api.RootResourceId
          RestApiId: !Ref Api 
          Integration:
              IntegrationHttpMethod: POST
              Type: AWS_PROXY
              PassthroughBehavior: WHEN_NO_MATCH
              Uri: !Join ["", ["arn:aws:apigateway:", "us-east-1", ":lambda:path/2015-03-31/functions/", !GetAtt MyFunction.Arn, "/invocations"] ]
    
      ProxyMethod:
          Type: 'AWS::ApiGateway::Method'
          Properties:
            HttpMethod: ANY
            ResourceId: !Ref Resource
            RestApiId: !Ref Api
            AuthorizationType: NONE
            Integration:
              IntegrationHttpMethod: POST
              Type: AWS_PROXY
              Uri: !Join ["", ["arn:aws:apigateway:", "us-east-1", ":lambda:path/2015-03-31/functions/", !GetAtt MyFunction.Arn, "/invocations"] ]
              PassthroughBehavior: WHEN_NO_MATCH
    
      FunctionPermissions:
        Type: "AWS::Lambda::Permission"
        Properties: 
          Action: "lambda:InvokeFunction"        
          FunctionName: !GetAtt MyFunction.Arn
          Principal: "apigateway.amazonaws.com"
          SourceArn: !Join [ "", ["arn:aws:execute-api:", !Ref "AWS::Region", ":", !Ref "AWS::AccountId", ":", !Ref Api, "/*" ] ] 
    
      Deployment:
        DependsOn:
          - MyFunction
          - RootMethod
          - ProxyMethod
        Type: 'AWS::ApiGateway::Deployment'
        Properties:
          RestApiId: !Ref Api
          StageName: prod
    

    我昨天(不工作)和这个(工作)之间的差异总结:

    1. Integration 部分中删除了 Credentials 对象。
    2. IntegrationHttpMethod 从 ANY 更改为 POST(感谢 Miles 指出这一点)
    3. FunctionPermissions 下将SourceArn 更改为以/* 结尾而不是/*/*/*

    虽然在这种情况下我的 lambda 函数的响应没有问题,但它的格式正确很重要。所以这是我的功能,希望将所有功能集中在一个地方对人们有所帮助。

    def lambda_handler(event, context):
        response = {
            "isBase64Encoded": "false",
            "statusCode": 200,
            "headers": { "Content-Type": "application/json"},
            "body": "hello from sample function"
        }
    
        return response
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-08-30
      • 2019-02-03
      • 2017-07-09
      • 2021-08-14
      • 2021-09-22
      • 2017-04-07
      • 2021-09-19
      相关资源
      最近更新 更多