简体   繁体   English

AWS Cloudformation无法向Lambda函数添加权限

[英]AWS Cloudformation unable to add permission to Lambda function

I am facing an issue on the Cloudformation template where POST methods are getting created and invoke permissions are being set properly, 我在Cloudformation模板上遇到一个问题,该模板中正在创建POST方法并已正确设置调用权限,
But the GET or any non POST methods are getting created but, 但是正在创建GET或任何非POST方法,但是,
do not seem to have invocation permission being set properly. 似乎没有正确设置调用权限。

Following is the working template with the POST method - 以下是带有POST方法的工作模板-

AWSTemplateFormatVersion: '2010-09-09'

Description: AWS API Gateway with a Lambda Integration

#Creating resusable parameters
Parameters:
  CorsOrigin:
    Type: String
    Default: "'*'"
  CorsHeaders:
    Type: String
    Default: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'"
  CorsMethods:
    Type: String
    Default: "'OPTIONS,GET,PUT,POST,DELETE'"

Resources:
  #Creating Lambda to act as a backend, returning Hello world
  BusinessLambda:
    Type: AWS::Lambda::Function
    Properties:
      Code:
        ZipFile: |
          exports.handler = async (event) => {
            let response = {
              'statusCode': 200,
              'headers': {
                'Access-Control-Allow-Origin': '*',
                'Content-Type': 'application/json'
              },
              'body': 'Hello, World!'
            };
            return response;
          };
      Description: AWS Lambda function
      FunctionName: 'BusinessLambda'
      Handler: index.handler
      MemorySize: 128
      Role: !Sub 'arn:aws:iam::${AWS::AccountId}:role/service-role/ScriptRole'
      Runtime: nodejs8.10
      Timeout: 15

  #Creating a Lambda function to act as an Authorizer, returns an allow IAM policy
  AuthorizerLambda:
    Type: 'AWS::Lambda::Function'
    Properties:
      FunctionName: 'AuthorizerLambda'
      Handler: handler.handler
      Runtime: nodejs8.10
      Code:
        S3Bucket: 'some-bucket-name'
        S3Key: 'stage/deployable/authPrivate.zip'
      Description: 'Auth test'
      MemorySize: 128
      Timeout: 15
      Role: !Sub 'arn:aws:iam::${AWS::AccountId}:role/service-role/ScriptRole'

  #Creating an API gateway called => test-api-gw
  RestApiGateway:
    Type: AWS::ApiGateway::RestApi
    Properties:
      Name: test-api-gw
      ApiKeySourceType: HEADER
      Description: An API Gateway with a Lambda Integration
      EndpointConfiguration:
        Types:
          - EDGE

  #Creating a url path called => /test
  RestApiResource:
    Type: AWS::ApiGateway::Resource
    Properties:
      ParentId: !GetAtt RestApiGateway.RootResourceId
      PathPart: 'test'
      RestApiId: !Ref RestApiGateway

  #Creating an API Gateway Custom Authorizer
  RestApiAuthorizer:
    Type: AWS::ApiGateway::Authorizer
    Properties: 
      AuthorizerUri: !Sub "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${AuthorizerLambda.Arn}/invocations"
      RestApiId: !Ref RestApiGateway
      Type: "REQUEST"
      IdentitySource: method.request.header.Authorization
      Name: custom_authorizer

  #Providing permission to Lambda to be used as an Authorizer for the API Gateway
  RestApiAuthorizerPermission:
    Type: "AWS::Lambda::Permission"
    Properties:
      Action: lambda:InvokeFunction
      FunctionName: !GetAtt AuthorizerLambda.Arn
      Principal: "apigateway.amazonaws.com"
      SourceArn: !Sub "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApiGateway}/authorizers/${RestApiAuthorizer}"

  #Creating a POST method with Custom Authorizer
  ApiGatewayMethod:
    Type: AWS::ApiGateway::Method
    Properties:
      ApiKeyRequired: false
      AuthorizationType: "CUSTOM"
      AuthorizerId: !Ref RestApiAuthorizer
      HttpMethod: POST
      Integration:
        Type: AWS_PROXY
        IntegrationHttpMethod: "POST"
        Uri: !Sub 'arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:${!stageVariables.lambdaAlias}/invocations'
        IntegrationResponses:
          - StatusCode: 200
            ResponseTemplates:
              application/json: $input.json('$')
            ResponseParameters:
              method.response.header.Access-Control-Allow-Headers: !Ref CorsHeaders
              method.response.header.Access-Control-Allow-Methods: !Ref CorsMethods
              method.response.header.Access-Control-Allow-Origin: !Ref CorsOrigin
        RequestTemplates:
          application/json: $input.json('$')
      MethodResponses:
        - 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
          StatusCode: '200'
      RequestParameters:
        method.request.querystring.name: false
      OperationName: 'lambda'
      ResourceId: !Ref RestApiResource
      RestApiId: !Ref RestApiGateway

  #Enabling CORS by creating an OPTIONS method on /test resource path
  APIGatewayOptionsMethod:
    Type: "AWS::ApiGateway::Method"
    Properties:
      ResourceId: !Ref RestApiResource
      RestApiId: !Ref RestApiGateway
      AuthorizationType: NONE
      HttpMethod: OPTIONS
      Integration:
        Type: MOCK
        IntegrationResponses:
          - ResponseParameters:
              method.response.header.Access-Control-Allow-Headers: !Ref CorsHeaders
              method.response.header.Access-Control-Allow-Methods: !Ref CorsMethods
              method.response.header.Access-Control-Allow-Origin: !Ref CorsOrigin
            ResponseTemplates:
              application/json: ''
            StatusCode: '200'
        PassthroughBehavior: WHEN_NO_MATCH
        RequestTemplates:
          application/json: '{"statusCode": 200}'
      MethodResponses:
        - ResponseModels:
            application/json: 'Empty'
          ResponseParameters:
            method.response.header.Access-Control-Allow-Headers: false
            method.response.header.Access-Control-Allow-Methods: false
            method.response.header.Access-Control-Allow-Origin: false
          StatusCode: '200'

  #Provide permission for API Gateway to Invoke Lambda
  LambdaPermission:
    Type: "AWS::Lambda::Permission"
    Properties:
      Action: "lambda:InvokeFunction"
      FunctionName: !GetAtt BusinessLambda.Arn
      Principal: "apigateway.amazonaws.com"
      SourceArn: !Sub "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApiGateway}/*/POST/test"

  #Deploying the API gateway
  ApiGatewayDeployment:
    Type: AWS::ApiGateway::Deployment
    DependsOn: ApiGatewayMethod
    Properties:
      Description: Lambda API Deployment
      RestApiId: !Ref RestApiGateway

  #Create a stage on API Gateway called => dev
  ApiGatewayStage:
    Type: AWS::ApiGateway::Stage
    Properties:
      DeploymentId: !Ref ApiGatewayDeployment
      Description: API GW Stage dev
      RestApiId: !Ref RestApiGateway
      StageName: 'dev'
      Variables: 
        'lambdaAlias' : 'BusinessLambda'

But if I change the method to GET, it doesn't work - 但是,如果我将方法更改为GET,它将无法正常工作-

#Creating a GET method with Custom Authorizer
  ApiGatewayMethod:
    Type: AWS::ApiGateway::Method
    Properties:
      ApiKeyRequired: false
      AuthorizationType: "CUSTOM"
      AuthorizerId: !Ref RestApiAuthorizer
      HttpMethod: GET
      Integration:
        Type: AWS_PROXY
        IntegrationHttpMethod: "GET"
        Uri: !Sub 'arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:${!stageVariables.lambdaAlias}/invocations'
        IntegrationResponses:
          - StatusCode: 200
            ResponseTemplates:
              application/json: $input.json('$')
            ResponseParameters:
              method.response.header.Access-Control-Allow-Headers: !Ref CorsHeaders
              method.response.header.Access-Control-Allow-Methods: !Ref CorsMethods
              method.response.header.Access-Control-Allow-Origin: !Ref CorsOrigin
        RequestTemplates:
          application/json: $input.json('$')
      MethodResponses:
        - 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
          StatusCode: '200'
      RequestParameters:
        method.request.querystring.name: false
      OperationName: 'lambda'
      ResourceId: !Ref RestApiResource
      RestApiId: !Ref RestApiGateway

#Provide permission for API Gateway to Invoke Lambda
  LambdaPermission:
    Type: "AWS::Lambda::Permission"
    Properties:
      Action: "lambda:InvokeFunction"
      FunctionName: !GetAtt BusinessLambda.Arn
      Principal: "apigateway.amazonaws.com"
      SourceArn: !Sub "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApiGateway}/*/GET/test"

The code for AuthorizerLambda is basically this - AuthorizerLambda的代码基本上是这样的-
https://github.com/awslabs/aws-apigateway-lambda-authorizer-blueprints/blob/master/blueprints/nodejs/index.js https://github.com/awslabs/aws-apigateway-lambda-authorizer-blueprints/blob/master/blueprints/nodejs/index.js

The /test API work with POST HTTP method , /test API与POST HTTP method
After changing to GET HTTP method I get the following error - 更改为GET HTTP method后,出现以下错误-

{
    "message": "Internal server error"
}

I found that in the GET case, the Authorizer is getting called, 我发现在GET情况下,授权者被调用了,
But control doesn't get passed to the Business Lambda function. 但是控制不会传递给Business Lambda函数。

To resolve this - 为了解决这个问题-
1. I have to remove the Authorizer from the method 1.我必须从方法中删除授权者
2. Run the add-permission command using CLI 2.使用CLI运行add-permission命令
3. Deploy the API 3.部署API
4. Add the Authorizer to the method 4.将授权者添加到方法中
5. Deploy again 5.再次部署

Related issue - 相关问题-
https://forums.aws.amazon.com/thread.jspa?threadID=240699 https://forums.aws.amazon.com/thread.jspa?threadID=240699

在此处输入图片说明

Do I need to do something like this - 我需要做这样的事情-

ApiGatewayMethod:
    Type: AWS::ApiGateway::Method
    Properties:
      ApiKeyRequired: false
      AuthorizationType: "CUSTOM"
      AuthorizerId: !Ref RestApiAuthorizer
      HttpMethod: GET
      Integration:
        Type: AWS_PROXY
        IntegrationHttpMethod: "POST"

Got this resolved by making IntegrationHttpMethod: "POST" , 通过使IntegrationHttpMethod: "POST"解决了此问题,
So irrespective of the Method's HTTP type, 因此,无论方法的HTTP类型如何,
The IntegrationHttpMethod must always be POST it seems. 看起来,IntegrationHttpMethod必须始终为POST。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 AWS CloudFormation中的Lambda函数 - Lambda Function in AWS CloudFormation 如何为使用 CloudFormation 模板创建的 AWS Lambda function 添加触发器? - How to add triggers for a AWS Lambda function created using a CloudFormation template? 在 CloudFormation 中创建 AWS WorkMail Lambda 调用权限 - Creating a AWS WorkMail Lambda invoke permission in CloudFormation 无法为以AWS :: CloudFormation :: CustomResource执行的AWS Lambda函数设置环境变量 - Unable to set environment variable for aws lambda function executed as AWS::CloudFormation::CustomResource AWS Lambda function 无法访问 AppSync GraphQL API 权限被拒绝 - AWS Lambda function unable to access AppSync GraphQL API - permission denied lambda function 未在 AWS 中使用 cloudformation 和管道进行更新 - lambda function is not being updated with cloudformation and pipeline in AWS 通过cloudformation添加在API网关中触发lambda的权限 - Add permission for triggering lambda in api gateway via cloudformation 无法将触发器添加到 AWS Lambda - Unable to add trigger to AWS Lambda 如何使用 CloudFormation Package 在 AWS Lambda 控制台中添加依赖文件 - How to add a dependency file in AWS Lambda Console with CloudFormation Package 无法运行 AWS lambda function - Unable to run AWS lambda function
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM