Lambda@edge 不是由原始请求事件触发的

Rom*_*oma 1 amazon-cloudfront aws-lambda-edge

我正在尝试使用 CloudFormation 配置 Lambda@edge 函数。部署模板后,一切都可以在控制台中找到,但是监听origin-request事件的 lambda 函数没有被触发。奇怪的是,一个viewer-request事件确实设法触发了一个功能。

我究竟做错了什么?我怎样才能让origin-request活动发挥作用?

这是我的模板:

AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Description: Deployment of Lambda@edge functions

Parameters:
  Stage:
    Type: String
    AllowedValues:
      - staging
      - production
    Default: staging
    Description: Stage that can be added to resource names
  CodeBucket:
    Type: String
    Description: The S3 Bucket name for latest code upload
  CodeKey:
    Type: String
    Description: The S3 Key for latest code upload

# Mappings:
#   AliasMap:
#     staging:
#       Alias: "staging-app.achrafsouk.com"
#     production:
#       Alias: "app.achrafsouk.com"
Resources:
  CFDistribution:
    Type: AWS::CloudFront::Distribution
    Properties:
      DistributionConfig:
        Enabled: true
        Logging:
          Bucket: XXX.s3.amazonaws.com
          IncludeCookies: false
          Prefix: !Sub ${Stage}
        PriceClass: PriceClass_100
        Comment:
          !Sub "Lambda@Edge - ${Stage}"
          # Aliases:
          #   - !FindInMap [AliasMap,
          # Ref: Stage, Alias]
        Origins:
          - CustomOriginConfig:
              OriginProtocolPolicy: https-only
            DomainName: !Sub "${Stage}.defaultOrigin.example.com"
            Id: defaultOrigin
            OriginCustomHeaders:
              - HeaderName: X-Node-Env
                HeaderValue: !Sub "${Stage}"
          - CustomOriginConfig:
              OriginProtocolPolicy: https-only
            DomainName: !Sub "${Stage}.another.example.com"
            Id: rateLimitsOrigin
            OriginCustomHeaders:
              - HeaderName: X-Node-Env
                HeaderValue: !Sub "${Stage}"
        DefaultCacheBehavior:
          ForwardedValues:
            Headers:
              - CloudFront-Viewer-Country
              - X-Request-Host
              - User-Agent
            QueryString: true
          ViewerProtocolPolicy: https-only
          TargetOriginId: defaultOrigin
          DefaultTTL: 0
          MaxTTL: 0
          LambdaFunctionAssociations:
            # - EventType: viewer-request
            #   LambdaFunctionARN:
            #     Ref: ViewerRequestLambdaFunction.Version
            - EventType: origin-request
              LambdaFunctionARN:
                Ref: OriginRequestLambdaFunction.Version
        CacheBehaviors:
          - ForwardedValues:
              Headers:
                - CloudFront-Viewer-Country
                - X-Request-Host
                - User-Agent
              QueryString: true
            ViewerProtocolPolicy: https-only
            DefaultTTL: 60
            MaxTTL: 60
            TargetOriginId: rateLimitsOrigin
            PathPattern: "/rate-limit*"
            LambdaFunctionAssociations:
              - EventType: origin-request
                LambdaFunctionARN:
                  Ref: GetRateLimitLambdaFunction.Version

  # ViewerRequestLambdaFunction:
  #   Type: AWS::Serverless::Function
  #   Properties:
  #     CodeUri:
  #       Bucket: !Sub ${CodeBucket}
  #       Key: !Sub ${CodeKey}
  #     Role: !GetAtt LambdaEdgeFunctionRole.Arn
  #     Runtime: nodejs10.x
  #     Handler: src/functions/viewerRequest.handler
  #     Timeout: 5
  #     AutoPublishAlias: live
  OriginRequestLambdaFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri:
        Bucket: !Sub ${CodeBucket}
        Key: !Sub ${CodeKey}
      Role: !GetAtt LambdaEdgeFunctionRole.Arn
      Runtime: nodejs10.x
      Handler: src/functions/originRequest.handler
      Timeout: 5
      AutoPublishAlias: live
  GetRateLimitLambdaFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri:
        Bucket: !Sub ${CodeBucket}
        Key: !Sub ${CodeKey}
      Role: !GetAtt LambdaEdgeFunctionRole.Arn
      Runtime: nodejs10.x
      Handler: src/functions/getRateLimit.handler
      Timeout: 5
      AutoPublishAlias: live

  LambdaEdgeFunctionRole:
    Type: "AWS::IAM::Role"
    Properties:
      Path: "/"
      ManagedPolicyArns:
        - "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Sid: "AllowLambdaServiceToAssumeRole"
            Effect: "Allow"
            Action:
              - "sts:AssumeRole"
            Principal:
              Service:
                - "lambda.amazonaws.com"
                - "edgelambda.amazonaws.com"

Outputs:
  # ViewerRequestLambdaFunctionVersion:
  #   Value: !Ref ViewerRequestLambdaFunction.Version

  OriginRequestLambdaFunctionVersion:
    Value: !Ref OriginRequestLambdaFunction.Version

  GetRateLimitLambdaFunctionVersion:
    Value: !Ref GetRateLimitLambdaFunction.Version

  CFDistribution:
    Description: Cloudfront Distribution Domain Name
    Value: !GetAtt CFDistribution.DomainName

Run Code Online (Sandbox Code Playgroud)

Rom*_*oma 7

因此,经过几个小时的痛苦尝试和错误后,解决方案让我眼前一亮:CloudFront 分发正在发出错误消息,说它无法连接到源,这是正确的 - 因为我已经在源定义中指定了虚拟域CloudFront 分配。

我的逻辑是,如果我的 lambda@edge 函数在到达源之前拦截了请求,那么源的域是否真实应该无关紧要。

事实证明,这是部分正确的。因为它接缝:

  • viewer-request 事件在尝试连接到源之前被触发,并且可以通过伪造。
  • origin-request 仅在尝试连接到原点后才会触发事件,因此您需要指定一些真实的内容。

希望我浪费的时间能帮助其他人探索相同的推理路径。