1

我通过 AWS CloudFormation 模板进行了以下 CloudFront 设置:

  CloudFrontDistribution:  
    Type: AWS::CloudFront::Distribution
    DependsOn:
    - LoggingBucket
    - LambdaEdgeFunction
    Properties:
      DistributionConfig:
        Comment: 'Route to multiple origins with CloudFront'
        Enabled: true
        IPV6Enabled: !Ref 'IPV6Enabled'
        Logging:
          Bucket: !Sub '${LoggingBucket}.s3.amazonaws.com'
        HttpVersion: http2
        Comment: !Join [ '', [!Ref 'AWS::StackName', ' Cloud Front']]
        Aliases: 
          - !Ref 'AlternateDomainNames'
        ViewerCertificate:
          AcmCertificateArn: !Ref ACMCertificateArn
          SslSupportMethod: !Ref 'SslSupportMethod' #sni-only
          MinimumProtocolVersion: !Ref 'MinimumProtocolVersion' #TLSv1.1_2016
        Origins:
        - Id: APIGOrigin
          DomainName: !Sub ${ApiGatewayId}.execute-api.eu-west-1.amazonaws.com
          OriginPath: !Sub /${ApiStage}
          CustomOriginConfig:
            HTTPSPort: 443
            OriginProtocolPolicy: https-only
          OriginCustomHeaders:
            - HeaderName: 'X-From-CDN'
              HeaderValue: !Ref VerifyFromCfHeaderVal
        DefaultCacheBehavior:
          AllowedMethods: ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"]
          CachedMethods: ["GET", "HEAD", "OPTIONS"]
          ForwardedValues:
            Headers:
            - Access-Control-Request-Headers
            - Access-Control-Request-Method
            - Origin
            - Authorization
            - Accept
            # - Host APIG needs to use SNI
            QueryString: !Ref 'QueryString'
            Cookies:
              Forward: !Ref 'ForwardCookies'
          TargetOriginId: APIGOrigin
          ViewerProtocolPolicy: https-only
          Compress: !Ref 'Compress'
          DefaultTTL: !Ref 'DefaultTTL'
          MaxTTL: !Ref 'MaxTTL'
          MinTTL: !Ref 'MinTTL'
          SmoothStreaming: 'false'
          # Lambda
          LambdaFunctionAssociations:
            - EventType: !Ref 'LambdaEventType'
              LambdaFunctionARN: !Ref 'LambdaEdgeVersion'
        CustomErrorResponses:
        - ErrorCachingMinTTL: 0
          ErrorCode: 400
        - ErrorCachingMinTTL: 1
          ErrorCode: 403
        - ErrorCachingMinTTL: 5
          ErrorCode: 500

因此,每次 API 网关源响应时,都会触发 Lambda@Edge,目前我将其设置为:

# LAMBDA@EDGE FUNCTION
  LambdaEdgeFunction:
    Type: 'AWS::Lambda::Function'
    Properties:
      Description: !Sub 'A custom Lambda@Edge function for serving custom headers from CloudFront Distribution'
      FunctionName: !Sub '${AppName}-lambda-edge-${Environment}'
      Handler: index.handler
      Role: !GetAtt 'LambdaEdgeIAMRole.Arn'
      MemorySize: 128
      Timeout: 5
      Code:
        ZipFile: !Sub |
          'use strict';

           exports.handler = (event, context, callback) => {
              console.log('Adding additional headers to CloudFront response.');

              const response = event.Records[0].cf.response;
              console.log("Response received:\n", JSON.stringify(response));
              response.headers['strict-transport-security'] = [{
              key: 'Strict-Transport-Security',
              value: 'max-age=86400; includeSubdomains; preload',
              }];
              response.headers['x-content-type-options'] = [{
              key: 'X-Content-Type-Options',
              value: 'nosniff',
              }];
              response.headers['x-frame-options'] = [{
                  key:   'X-Frame-Options',
                  value: "DENY"
              }];
              response.headers['content-security-policy'] = [{
                  key:   'Content-Security-Policy',
                  value: "default-src 'none'; img-src 'self'; script-src 'self'; style-src 'self'; object-src 'none'"
              }];
              response.headers['x-xss-protection'] = [{
                  key:   'X-XSS-Protection',
                  value: "1; mode=block"
              }];
              response.headers['referrer-policy'] = [{
                  key:   'Referrer-Policy',
                  value: "same-origin"
              }];
              console.log('Remove Content-Length headers from CloudFront response..');
              delete response.headers["Content-Length"]
              callback(null, response);
            };
      Runtime: nodejs12.x

当我向端点发送请求时,我仍然可以Content-Length在响应中看到:

curl -i --http1.1 \ 
  --url https://cdn.domain.tld/s/94163e58494
HTTP/1.1 301 Moved Permanently
Content-Type: text/html; charset=UTF-8
Content-Length: 316
Connection: keep-alive
Server: CloudFront
Date: Thu, 30 Apr 2020 17:54:54 GMT
Referrer-Policy: same-origin
X-Frame-Options: DENY
x-amz-apigw-id: Lz-VPFnLDoEFbig=
Cache-Control: max-age=0, no-cache, private
Location: http://google.com
Via: 1.1 15c672a1a9***.cloudfront.net (CloudFront), 1.1 0b7c0b1558a4*****.cloudfront.net (CloudFront)
Strict-Transport-Security: max-age=86400; includeSubdomains; preload
X-Content-Type-Options: nosniff
Content-Security-Policy: default-src 'none'; img-src 'self'; script-src 'self'; style-src 'self'; object-src 'none'
X-XSS-Protection: 1; mode=block
x-amzn-RequestId: 0a29a0a9-c14f-4c14-b773-d57813cf91c3
X-Amzn-Trace-Id: Root=1-5eab10ee-50d2c5e08498c8689ad025e0;Sampled=0
X-Amz-Cf-Pop: LHR52-C1
X-Cache: Miss from cloudfront
X-Amz-Cf-Pop: LHR52-C1
X-Amz-Cf-Id: c1KMNm2DOHzfzsIYLBeShWVlxVyaN8yO33hZ3aAAjVIR03x2gx49sw==


<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="refresh" content="0;url='http://google.com'" />

        <title>Redirecting to http://google.com</title>
    </head>
    <body>
        Redirecting to <a href="http://google.com">http://google.com</a>.
    </body>
</html>

我已遵循https://aws.amazon.com/blogs/networking-and-content-delivery/adding-http-security-headers-using-lambdaedge-and-amazon-cloudfront/指南,但我仍然无法看看如何Content-Length从响应中删除 - 这可能吗?

非常感谢任何建议

4

2 回答 2

1

是什么LambdaEventType?应该是viewer-response编辑 CloudFront 的响应。

您的函数应该删除content-length而不是Content-Length因为标题名称在 headers 数组中应为小写。

delete response.headers["content-length"]

文档说:

headers 对象中的键是标准 HTTP 标头名称的小写版本。使用小写键可以让您不区分大小写地访问标头值。

于 2020-05-02T22:03:47.550 回答
0

当您收到此错误时,您似乎无法修改只读标头:

The Lambda function result failed validation: The function tried to add, delete, or change a read-only header.
于 2020-05-03T13:37:57.177 回答