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

时间:2019-09-06 02:31:04

标签: amazon-web-services amazon-cloudformation

我在Cloudformation模板上遇到了一个问题,该模板中正在创建POST方法并正确设置了调用权限,
但是正在创建GET或任何非POST方法,但是,
似乎没有正确设置调用权限。

以下是具有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'

但是,如果我将方法更改为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"

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

/test API与POST HTTP method一起使用,
更改为GET HTTP method后,出现以下错误-

{
    "message": "Internal server error"
}

我发现在GET情况下,授权者被调用,
但是控制不会传递给Business Lambda函数。

要解决此问题-
1.我必须从方法中删除授权者
2.使用CLI运行add-permission命令
3.部署API
4.将授权者添加到方法中
5.再次部署

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

enter image description here

我需要做这样的事情吗?

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

1 个答案:

答案 0 :(得分:0)

通过使 income increment user 0 100 2 Bob 0 200 4 Bob 0 300 6 Bob 0 400 8 Bob 0 500 10 Bob 0 600 12 Bob 0 700 14 Bob 0 800 16 Bob 0 900 18 Bob 0 1000 20 Bob 1 400 6 Jane 1 800 12 Jane 2 300 4 Alice 2 600 8 Alice 2 900 12 Alice 来解决此问题,
因此,无论该方法的HTTP类型如何,
IntegrationHttpMethod都必须始终为POST。