API网关自定义授权方内部服务器错误

问题描述 投票:0回答:1

我有以下 Cloudformation 模板,该模板使用自定义 Lambda 授权方部署 HTTP API 网关,该授权方可传送到 SQS 队列。我使用此处未显示的另一个 lambda 处理队列中的消息。当我在没有启用授权的情况下部署此模板时(在路线中将

AuthorizationType
CUSTOM
设置为
NONE
,并注释掉
AuthorizerId: !Ref APIAuthorizer
),整个过程正常进行,我看到我的消息流从 API Gateway 通过 SQS 流向订阅 Lambda 进行处理。但是,当我启用授权时,我看到我的消息进入 Auth Lambda,然后在 Postman 中收到内部服务器错误。

自定义身份验证显然存在问题,但是,在尝试了几天不同的操作后,我找不到问题的原因。

我的理解是我只需要在返回的策略中授权routeArn,但是,也许我还需要为SQS权限做一些事情?

这是我的模板(不包括最终的 lambda)。


  Queue:
    Type: AWS::SQS::Queue
    Properties:
      QueueName: my-queue

  QueuePolicy:
    DependsOn: ["Queue"]
    Type: AWS::SQS::QueuePolicy
    Properties:
      PolicyDocument:
        Statement:
          - Action: SQS:*
            Effect: Allow
            Principal: '*'
            Resource: !GetAtt Queue.Arn
        Version: '2012-10-17'
      Queues:
        - !Ref Queue
        
  ApiGatewayToSQSRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
        - Effect: Allow
          Principal:
            Service:
            - apigateway.amazonaws.com
          Action:
          - sts:AssumeRole
      RoleName: ApiGatewayToSQSRole
      Policies:
      - PolicyName: ApiGatewayLogsPolicy
        PolicyDocument:
          Version: '2012-10-17'
          Statement:
          - Action: sqs:SendMessage
            Effect: Allow
            Resource: !GetAtt 'Queue.Arn'
          - Action:
              - logs:CreateLogGroup
              - logs:CreateLogStream
              - logs:DescribeLogGroups
              - logs:DescribeLogStreams
              - logs:PutLogEvents
              - logs:GetLogEvents
              - logs:FilterLogEvents
            Effect: Allow
            Resource: "*"

  ApiGateway:
    Type: 'AWS::ApiGatewayV2::Api'
    DeletionPolicy: Delete
    Properties:
      Name: "API Gateway to SQS"
      ProtocolType: 'HTTP'

  ApiGatewayStage:
    Type: AWS::ApiGatewayV2::Stage
    Properties:
      ApiId: !Ref ApiGateway
      StageName: dev
      AutoDeploy: true
  
  Integration:
    Type: AWS::ApiGatewayV2::Integration
    Properties:
      ApiId: !Ref ApiGateway
      CredentialsArn: !GetAtt ApiGatewayToSQSRole.Arn
      PayloadFormatVersion: "1.0"
      IntegrationType: AWS_PROXY
      IntegrationSubtype: SQS-SendMessage
      RequestParameters:
        QueueUrl: !Ref Queue
        MessageBody: $request.body
  
  Route:
    Type: AWS::ApiGatewayV2::Route
    DependsOn:
      - ApiGateway
      - Integration
    Properties:
      ApiId: !Ref ApiGateway
      RouteKey: 'POST /send'
      AuthorizationType: CUSTOM
      AuthorizerId: !Ref APIAuthorizer
      Target: !Sub integrations/${Integration}

  APIAuthorizer:
    Type: AWS::ApiGatewayV2::Authorizer
    Properties:
      Name: APIAuthorizer
      ApiId: !Ref ApiGateway
      AuthorizerType: REQUEST
      AuthorizerUri: !Join
        - ""
        - - "arn:"
          - !Ref "AWS::Partition"
          - ":apigateway:"
          - !Ref "AWS::Region"
          - ":lambda:path/2015-03-31/functions/"
          - !GetAtt AuthorizerFunction.Arn
          - /invocations
      AuthorizerResultTtlInSeconds: 300
      AuthorizerPayloadFormatVersion: 2.0
      EnableSimpleResponses: true
      IdentitySource:
        - $request.header.authorization

  AuthorizePermission:
    Type: AWS::Lambda::Permission
    DependsOn:
      - ApiGateway
      - AuthorizerFunction
    Properties:
      Action: lambda:InvokeFunction
      FunctionName: !Ref AuthorizerFunction
      Principal: apigateway.amazonaws.com
  AuthHandlerServiceRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Action: 'sts:AssumeRole'
            Effect: Allow
            Principal:
              Service: lambda.amazonaws.com
        Version: 2012-10-17
      ManagedPolicyArns:
        - !Join
          - ''
          - - 'arn:'
            - !Ref 'AWS::Partition'
            - ':iam::aws:policy/service-role/AWSLambdaBasicExecutionRole'
  AuthorizerFunction:
    Type: AWS::Serverless::Function
    Properties:
      FunctionName: authorizer-lambda
      Role: !GetAtt [AuthHandlerServiceRole, Arn]
      CodeUri: functions/core_authorizer_lambda
      Handler: index.handler
      Runtime: python3.11
      Tags:
        Name: authorizer-lambda
        project: my-project

这是我的授权者 lambda 函数

def generate_policy(principal_id: Union[int, str, None], effect: str, resource: str) -> dict:
    """ return a valid AWS policy response """
    auth_response = {'principalId': principal_id}
    if effect and resource:
        policy_document = {
            'Version': '2012-10-17',
            'Statement': [
                {
                    'Sid': 'InvokeAPIStatement',
                    'Action': 'execute-api:Invoke',
                    'Effect': effect,
                    'Resource': resource
                }
            ]
        }
        auth_response['policyDocument'] = policy_document
    return auth_response


def handler(event, context) -> dict:
    try:
        print("event:", event)
        print("context:", context)
        
        route_arn = event.get('routeArn')
        
        return generate_policy('me', 'Allow', route_arn)
    except Exception as e:
        logging.exception(e)
        return {
            'statusCode': 500
        }

我用

调用它
{
    "body": "Hey aws! How are you today?",
    "headers": {
        "Accept": "application/json",
        "authorization": "Bearer <token>"
    }
}

我尝试了不同的模板设置,并尽可能简化一切。

amazon-web-services aws-lambda aws-cloudformation aws-api-gateway amazon-sqs
1个回答
0
投票

不要使用

 route_arn = event.get('routeArn')
,而是使用
methodArn
作为政策中的
Resource

这是您需要更改的代码。

methodArn = event.get('methodArn')
        
return generate_policy('me', 'Allow', methodArn)
© www.soinside.com 2019 - 2024. All rights reserved.