1

我正在尝试使用 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

4

2 回答 2

8

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

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

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

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

希望我浪费的时间将有助于其他人探索同样的推理路径。

于 2019-12-15T23:20:48.980 回答
0

万一它在将来帮助某人解决这个问题 - 我注意到origin-response(我不小心选择而不是)事件(大部分)为我工作,但日志origin-request中仍然有大量,并且“查看者请求的百分比OriginConnectError按结果类型”报告显示错误率很高。

事实证明它只是在工作,因为我将我的源连接设置为https-only,但我的源(一个空的 s3 存储桶)只接受 http 连接 - 由于某种原因,事件仍在被触发。

将源连接更改为正确的http-only完全停止了工作origin-response,直到我还将事件类型更正为origin-request

因此,一般来说,检查 OriginProtocolPolicyhttp-only是否您使用的是 s3 存储桶源。如果它错了,有时事情可能看起来仍然有效,但并非总是如此,你最终会遇到高错误率。

于 2021-04-13T08:18:56.743 回答