Example #1
0
 def get_lambda_associations(
         self) -> List[cloudfront.LambdaFunctionAssociation]:
     """Retrieve any lambda associations from the instance variables."""
     # If custom associations defined, use them
     if self.variables["lambda_function_associations"]:
         return [
             cloudfront.LambdaFunctionAssociation(
                 EventType=x["type"], LambdaFunctionARN=x["arn"])
             for x in self.variables["lambda_function_associations"]
         ]
     return []
Example #2
0
    def get_directory_index_lambda_association(  # pylint: disable=no-self-use
        self,
        lambda_associations,  # List[cloudfront.LambdaFunctionAssociation]
        directory_index_rewrite_version):  # awslambda.Version
        # type: (...) ->  List[cloudfront.LambdaFunctionAssociation]
        """Retrieve the directory index lambda associations with the added rewriter.

        Args:
            lambda_associations [List(Any)]: The lambda associations
            directory_index_rewrite_version [Any]: The directory index rewrite version
        """
        lambda_associations.append(
            cloudfront.LambdaFunctionAssociation(
                EventType='origin-request',
                LambdaFunctionARN=directory_index_rewrite_version.ref()))
        return lambda_associations
Example #3
0
    def get_directory_index_lambda_association(
        lambda_associations: List[cloudfront.LambdaFunctionAssociation],
        directory_index_rewrite_version: awslambda.Version,
    ) -> List[cloudfront.LambdaFunctionAssociation]:
        """Retrieve the directory index lambda associations with the added rewriter.

        Args:
            lambda_associations: The lambda associations.
            directory_index_rewrite_version: The directory index rewrite version.

        """
        lambda_associations.append(
            cloudfront.LambdaFunctionAssociation(
                EventType="origin-request",
                LambdaFunctionARN=directory_index_rewrite_version.ref(),
            ))
        return lambda_associations
Example #4
0
    def get_lambda_associations(self):
        # type: () -> List[cloudfront.LambdaFunctionAssociation]
        """Retrieve any lambda associations from the instance variables.

        Return:
            List of Lambda Function association variables

        """
        variables = self.get_variables()

        # If custom associations defined, use them
        if variables["lambda_function_associations"]:
            return [
                cloudfront.LambdaFunctionAssociation(
                    EventType=x["type"], LambdaFunctionARN=x["arn"])
                for x in variables["lambda_function_associations"]
            ]
        return []
Example #5
0
    def distribution(self) -> cloudfront.Distribution:
        """Return cloudfront distribution with bucket as origin."""
        origin = cloudfront.Origin(
            S3OriginConfig=cloudfront.S3OriginConfig(OriginAccessIdentity=Join(
                "",
                [
                    "origin-access-identity/cloudfront/",
                    Ref(self.origin_access_identity),
                ],
            )),
            DomainName=f"{self.bucket.name}.s3.amazonaws.com",
            Id="S3Origin",
        )
        cache_params = {
            "AllowedMethods": ["GET", "HEAD", "OPTIONS"],
            "CachePolicyId": Ref(self.cache_policy),
            "TargetOriginId": "S3Origin",
            "ViewerProtocolPolicy": "redirect-to-https",
        }
        if self.lambda_edge_function_arns:
            cache_params["LambdaFunctionAssociations"] = [
                cloudfront.LambdaFunctionAssociation(
                    EventType="viewer-request", LambdaFunctionARN=lambda_arn)
                for lambda_arn in self.lambda_edge_function_arns
            ]

        default_cache_behavior = cloudfront.DefaultCacheBehavior(
            **cache_params)
        return cloudfront.Distribution(
            name_to_id(self.name),
            DistributionConfig=cloudfront.DistributionConfig(
                Aliases=self.aliases,
                DefaultRootObject=self.root_object,
                DefaultCacheBehavior=default_cache_behavior,
                Enabled="True",
                HttpVersion="http2",
                Origins=[origin],
                ViewerCertificate=cloudfront.ViewerCertificate(
                    AcmCertificateArn=self.certificate_arn,
                    SslSupportMethod="sni-only",
                    MinimumProtocolVersion="TLSv1.2_2021",
                ),
            ),
        )
Example #6
0
    def get_lambda_associations(self):
        # type: () -> List[cloudfront.LambdaFunctionAssociation]
        """Retrieve any lambda associations from the instance variables.

        Keyword Args:
            directory_index_rewrite_version (dict): The directory index rewrite lambda version
                resource

        Return:
            array: Array of lambda function association variables
        """
        variables = self.get_variables()

        # If custom associations defined, use them
        if variables['lambda_function_associations']:
            return [
                cloudfront.LambdaFunctionAssociation(
                    EventType=x['type'], LambdaFunctionARN=x['arn'])
                for x in variables['lambda_function_associations']
            ]
        return []
Example #7
0
    def get_distribution_options(self,
                                 bucket,  # type: s3.Bucket
                                 oai,  # type: cloudfront.CloudFrontOriginAccessIdentity
                                 lambda_funcs,  # type: List[cloudfront.LambdaFunctionAssociation]
                                 check_auth_lambda_version,  # type: awslambda.Version
                                 http_headers_lambda_version,  # type: awslambda.Version
                                 parse_auth_lambda_version,  # type: awslambda.Version
                                 refresh_auth_lambda_version,  # type: awslambda.Version
                                 sign_out_lambda_version  # type: awslambda.Version
                                ):  # noqa: E124
        # type: (...) -> Dict[str, Any]
        """Retrieve the options for our CloudFront distribution.

        Keyword Args:
            bucket (dict): The bucket resource
            oai (dict): The origin access identity resource

        Return:
            dict: The CloudFront Distribution Options

        """
        variables = self.get_variables()

        default_cache_behavior_lambdas = lambda_funcs
        default_cache_behavior_lambdas.append(
            cloudfront.LambdaFunctionAssociation(
                EventType='viewer-request',
                LambdaFunctionARN=check_auth_lambda_version.ref()
            )
        )
        default_cache_behavior_lambdas.append(
            cloudfront.LambdaFunctionAssociation(
                EventType='origin-response',
                LambdaFunctionARN=http_headers_lambda_version.ref()
            )
        )

        return {
            'Aliases': self.add_aliases(),
            'Origins': [
                cloudfront.Origin(
                    DomainName=Join(
                        '.',
                        [bucket.ref(),
                         's3.amazonaws.com']),
                    S3OriginConfig=cloudfront.S3OriginConfig(
                        OriginAccessIdentity=Join(
                            '',
                            ['origin-access-identity/cloudfront/',
                             oai.ref()])
                    ),
                    Id='protected-bucket'
                )
            ],
            'CacheBehaviors': [
                cloudfront.CacheBehavior(
                    PathPattern=variables['RedirectPathSignIn'],
                    Compress=True,
                    ForwardedValues=cloudfront.ForwardedValues(
                        QueryString=True
                    ),
                    LambdaFunctionAssociations=[
                        cloudfront.LambdaFunctionAssociation(
                            EventType='viewer-request',
                            LambdaFunctionARN=parse_auth_lambda_version.ref()
                        )
                    ],
                    TargetOriginId='protected-bucket',
                    ViewerProtocolPolicy="redirect-to-https"
                ),
                cloudfront.CacheBehavior(
                    PathPattern=variables['RedirectPathAuthRefresh'],
                    Compress=True,
                    ForwardedValues=cloudfront.ForwardedValues(
                        QueryString=True
                    ),
                    LambdaFunctionAssociations=[
                        cloudfront.LambdaFunctionAssociation(
                            EventType='viewer-request',
                            LambdaFunctionARN=refresh_auth_lambda_version.ref()
                        )
                    ],
                    TargetOriginId='protected-bucket',
                    ViewerProtocolPolicy="redirect-to-https"
                ),
                cloudfront.CacheBehavior(
                    PathPattern=variables['SignOutUrl'],
                    Compress=True,
                    ForwardedValues=cloudfront.ForwardedValues(
                        QueryString=True
                    ),
                    LambdaFunctionAssociations=[
                        cloudfront.LambdaFunctionAssociation(
                            EventType='viewer-request',
                            LambdaFunctionARN=sign_out_lambda_version.ref()
                        )
                    ],
                    TargetOriginId='protected-bucket',
                    ViewerProtocolPolicy="redirect-to-https"
                ),
            ],
            'DefaultCacheBehavior': cloudfront.DefaultCacheBehavior(
                AllowedMethods=['GET', 'HEAD'],
                Compress=True,
                DefaultTTL='86400',
                ForwardedValues=cloudfront.ForwardedValues(
                    QueryString=True,
                ),
                LambdaFunctionAssociations=default_cache_behavior_lambdas,
                TargetOriginId='protected-bucket',
                ViewerProtocolPolicy='redirect-to-https'
            ),
            'DefaultRootObject': 'index.html',
            'Logging': self.add_logging_bucket(),
            'PriceClass': variables['PriceClass'],
            'Enabled': True,
            'WebACLId': self.add_web_acl(),
            'CustomErrorResponses': self._get_error_responses(),
            'ViewerCertificate': self.add_acm_cert()
        }
Example #8
0
    def create_template(self):
        """Create template (main function called by Stacker)."""
        template = self.template
        variables = self.get_variables()
        template.set_version('2010-09-09')
        template.set_description('Static Website - Bucket and Distribution')

        # Conditions
        template.add_condition(
            'AcmCertSpecified',
            And(Not(Equals(variables['AcmCertificateArn'].ref, '')),
                Not(Equals(variables['AcmCertificateArn'].ref, 'undefined')))
        )
        template.add_condition(
            'AliasesSpecified',
            And(Not(Equals(Select(0, variables['Aliases'].ref), '')),
                Not(Equals(Select(0, variables['Aliases'].ref), 'undefined')))
        )
        template.add_condition(
            'CFLoggingEnabled',
            And(Not(Equals(variables['LogBucketName'].ref, '')),
                Not(Equals(variables['LogBucketName'].ref, 'undefined')))
        )
        template.add_condition(
            'DirectoryIndexSpecified',
            And(Not(Equals(variables['RewriteDirectoryIndex'].ref, '')),
                Not(Equals(variables['RewriteDirectoryIndex'].ref, 'undefined')))  # noqa
        )
        template.add_condition(
            'WAFNameSpecified',
            And(Not(Equals(variables['WAFWebACL'].ref, '')),
                Not(Equals(variables['WAFWebACL'].ref, 'undefined')))
        )

        # Resources
        oai = template.add_resource(
            cloudfront.CloudFrontOriginAccessIdentity(
                'OAI',
                CloudFrontOriginAccessIdentityConfig=cloudfront.CloudFrontOriginAccessIdentityConfig(  # noqa pylint: disable=line-too-long
                    Comment='CF access to website'
                )
            )
        )

        bucket = template.add_resource(
            s3.Bucket(
                'Bucket',
                AccessControl=s3.Private,
                LifecycleConfiguration=s3.LifecycleConfiguration(
                    Rules=[
                        s3.LifecycleRule(
                            NoncurrentVersionExpirationInDays=90,
                            Status='Enabled'
                        )
                    ]
                ),
                VersioningConfiguration=s3.VersioningConfiguration(
                    Status='Enabled'
                ),
                WebsiteConfiguration=s3.WebsiteConfiguration(
                    IndexDocument='index.html',
                    ErrorDocument='error.html'
                )
            )
        )
        template.add_output(Output(
            'BucketName',
            Description='Name of website bucket',
            Value=bucket.ref()
        ))

        allowcfaccess = template.add_resource(
            s3.BucketPolicy(
                'AllowCFAccess',
                Bucket=bucket.ref(),
                PolicyDocument=PolicyDocument(
                    Version='2012-10-17',
                    Statement=[
                        Statement(
                            Action=[awacs.s3.GetObject],
                            Effect=Allow,
                            Principal=Principal(
                                'CanonicalUser',
                                oai.get_att('S3CanonicalUserId')
                            ),
                            Resource=[
                                Join('', [bucket.get_att('Arn'),
                                          '/*'])
                            ]
                        )
                    ]
                )
            )
        )

        cfdirectoryindexrewriterole = template.add_resource(
            iam.Role(
                'CFDirectoryIndexRewriteRole',
                Condition='DirectoryIndexSpecified',
                AssumeRolePolicyDocument=PolicyDocument(
                    Version='2012-10-17',
                    Statement=[
                        Statement(
                            Effect=Allow,
                            Action=[awacs.sts.AssumeRole],
                            Principal=Principal('Service',
                                                ['lambda.amazonaws.com',
                                                 'edgelambda.amazonaws.com'])
                        )
                    ]
                ),
                ManagedPolicyArns=[
                    IAM_ARN_PREFIX + 'AWSLambdaBasicExecutionRole'
                ]
            )
        )

        cfdirectoryindexrewrite = template.add_resource(
            awslambda.Function(
                'CFDirectoryIndexRewrite',
                Condition='DirectoryIndexSpecified',
                Code=awslambda.Code(
                    ZipFile=Join(
                        '',
                        ["'use strict';\n",
                         "exports.handler = (event, context, callback) => {\n",
                         "\n",
                         "    // Extract the request from the CloudFront event that is sent to Lambda@Edge\n",  # noqa pylint: disable=line-too-long
                         "    var request = event.Records[0].cf.request;\n",
                         "    // Extract the URI from the request\n",
                         "    var olduri = request.uri;\n",
                         "    // Match any '/' that occurs at the end of a URI. Replace it with a default index\n",  # noqa pylint: disable=line-too-long
                         "    var newuri = olduri.replace(/\\/$/, '\\/",
                         variables['RewriteDirectoryIndex'].ref,
                         "');\n",  # noqa
                         "    // Log the URI as received by CloudFront and the new URI to be used to fetch from origin\n",  # noqa pylint: disable=line-too-long
                         "    console.log(\"Old URI: \" + olduri);\n",
                         "    console.log(\"New URI: \" + newuri);\n",
                         "    // Replace the received URI with the URI that includes the index page\n",  # noqa pylint: disable=line-too-long
                         "    request.uri = newuri;\n",
                         "    // Return to CloudFront\n",
                         "    return callback(null, request);\n",
                         "\n",
                         "};\n"]
                    )
                ),
                Description='Rewrites CF directory HTTP requests to default page',  # noqa
                Handler='index.handler',
                Role=cfdirectoryindexrewriterole.get_att('Arn'),
                Runtime='nodejs8.10'
            )
        )

        # Generating a unique resource name here for the Lambda version, so it
        # updates automatically if the lambda code changes
        code_hash = hashlib.md5(
            str(cfdirectoryindexrewrite.properties['Code'].properties['ZipFile'].to_dict()).encode()  # noqa pylint: disable=line-too-long
        ).hexdigest()

        cfdirectoryindexrewritever = template.add_resource(
            awslambda.Version(
                'CFDirectoryIndexRewriteVer' + code_hash,
                Condition='DirectoryIndexSpecified',
                FunctionName=cfdirectoryindexrewrite.ref()
            )
        )

        # If custom associations defined, use them
        if variables['lambda_function_associations']:
            lambda_function_associations = [
                cloudfront.LambdaFunctionAssociation(
                    EventType=x['type'],
                    LambdaFunctionARN=x['arn']
                ) for x in variables['lambda_function_associations']
            ]
        else:  # otherwise fallback to pure CFN condition
            lambda_function_associations = If(
                'DirectoryIndexSpecified',
                [cloudfront.LambdaFunctionAssociation(
                    EventType='origin-request',
                    LambdaFunctionARN=cfdirectoryindexrewritever.ref()
                )],
                NoValue
            )

        cfdistribution = template.add_resource(
            get_cf_distribution_class()(
                'CFDistribution',
                DependsOn=allowcfaccess.title,
                DistributionConfig=get_cf_distro_conf_class()(
                    Aliases=If(
                        'AliasesSpecified',
                        variables['Aliases'].ref,
                        NoValue
                    ),
                    Origins=[
                        get_cf_origin_class()(
                            DomainName=Join(
                                '.',
                                [bucket.ref(),
                                 's3.amazonaws.com']),
                            S3OriginConfig=get_s3_origin_conf_class()(
                                OriginAccessIdentity=Join(
                                    '',
                                    ['origin-access-identity/cloudfront/',
                                     oai.ref()])
                            ),
                            Id='S3Origin'
                        )
                    ],
                    DefaultCacheBehavior=cloudfront.DefaultCacheBehavior(
                        AllowedMethods=['GET', 'HEAD'],
                        Compress=False,
                        DefaultTTL='86400',
                        ForwardedValues=cloudfront.ForwardedValues(
                            Cookies=cloudfront.Cookies(Forward='none'),
                            QueryString=False,
                        ),
                        LambdaFunctionAssociations=lambda_function_associations,  # noqa
                        TargetOriginId='S3Origin',
                        ViewerProtocolPolicy='redirect-to-https'
                    ),
                    DefaultRootObject='index.html',
                    Logging=If(
                        'CFLoggingEnabled',
                        cloudfront.Logging(
                            Bucket=Join('.',
                                        [variables['LogBucketName'].ref,
                                         's3.amazonaws.com'])
                        ),
                        NoValue
                    ),
                    PriceClass=variables['PriceClass'].ref,
                    Enabled=True,
                    WebACLId=If(
                        'WAFNameSpecified',
                        variables['WAFWebACL'].ref,
                        NoValue
                    ),
                    ViewerCertificate=If(
                        'AcmCertSpecified',
                        cloudfront.ViewerCertificate(
                            AcmCertificateArn=variables['AcmCertificateArn'].ref,  # noqa
                            SslSupportMethod='sni-only'
                        ),
                        NoValue
                    )
                )
            )
        )
        template.add_output(Output(
            'CFDistributionId',
            Description='CloudFront distribution ID',
            Value=cfdistribution.ref()
        ))
        template.add_output(
            Output(
                'CFDistributionDomainName',
                Description='CloudFront distribution domain name',
                Value=cfdistribution.get_att('DomainName')
            )
        )
Example #9
0
     ),
 ],
 DefaultRootObject=
 "index.html",  # Needed for this example only, adapt to your requirements
 CacheBehaviors=[
     # If you have additional cache behaviours,
     # make sure that (at least) the behaviour matching
     # /auth-89CE3FEF-FCF6-43B3-9DBA-7C410CAAE220/set-cookie
     # has the Lambda-function associated.
 ],
 DefaultCacheBehavior=cloudfront.DefaultCacheBehavior(
     ViewerProtocolPolicy=
     'redirect-to-https',  # HTTPS required. Cookies need to be sent securely
     LambdaFunctionAssociations=[
         cloudfront.LambdaFunctionAssociation(
             EventType='viewer-request',
             LambdaFunctionARN=Ref(param_authorizer_lae_arn)),
     ],
     # Rest of config as per your needs
     TargetOriginId='ExampleS3',
     ForwardedValues=cloudfront.ForwardedValues(
         QueryString=True,
         Cookies=cloudfront.Cookies(
             Forward=
             'all',  # Don't do this. Done here to validate cookie-removal logic
         ),
     ),
 ),
 ViewerCertificate=cloudfront.ViewerCertificate(
     AcmCertificateArn=Ref(acm_cert),
     SslSupportMethod='sni-only',
Example #10
0
    def get_distribution_options(
        self,
        bucket: s3.Bucket,
        oai: cloudfront.CloudFrontOriginAccessIdentity,
        lambda_funcs: List[cloudfront.LambdaFunctionAssociation],
        check_auth_lambda_version: awslambda.Version,
        http_headers_lambda_version: awslambda.Version,
        parse_auth_lambda_version: awslambda.Version,
        refresh_auth_lambda_version: awslambda.Version,
        sign_out_lambda_version: awslambda.Version,
    ) -> Dict[str, Any]:
        """Retrieve the options for our CloudFront distribution.

        Keyword Args:
            bucket: The bucket resource.
            oai: The origin access identity resource.
            lambda_funcs: List of Lambda Function associations.
            check_auth_lambda_version: Lambda Function Version to use.
            http_headers_lambda_version: Lambda Function Version to use.
            parse_auth_lambda_version: Lambda Function Version to use.
            refresh_auth_lambda_version: Lambda Function Version to use.
            sign_out_lambda_version: Lambda Function Version to use.

        Return:
            The CloudFront Distribution Options.

        """
        default_cache_behavior_lambdas = lambda_funcs
        default_cache_behavior_lambdas.append(
            cloudfront.LambdaFunctionAssociation(
                EventType="viewer-request",
                LambdaFunctionARN=check_auth_lambda_version.ref(),
            ))
        default_cache_behavior_lambdas.append(
            cloudfront.LambdaFunctionAssociation(
                EventType="origin-response",
                LambdaFunctionARN=http_headers_lambda_version.ref(),
            ))

        return {
            "Aliases":
            self.add_aliases(),
            "Origins": [
                cloudfront.Origin(
                    DomainName=Join(".", [bucket.ref(), "s3.amazonaws.com"]),
                    S3OriginConfig=cloudfront.
                    S3OriginConfig(OriginAccessIdentity=Join(
                        "", ["origin-access-identity/cloudfront/",
                             oai.ref()])),
                    Id="protected-bucket",
                )
            ],
            "CacheBehaviors": [
                cloudfront.CacheBehavior(
                    PathPattern=self.variables["RedirectPathSignIn"],
                    Compress=True,
                    ForwardedValues=cloudfront.ForwardedValues(
                        QueryString=True),
                    LambdaFunctionAssociations=[
                        cloudfront.LambdaFunctionAssociation(
                            EventType="viewer-request",
                            LambdaFunctionARN=parse_auth_lambda_version.ref(),
                        )
                    ],
                    TargetOriginId="protected-bucket",
                    ViewerProtocolPolicy="redirect-to-https",
                ),
                cloudfront.CacheBehavior(
                    PathPattern=self.variables["RedirectPathAuthRefresh"],
                    Compress=True,
                    ForwardedValues=cloudfront.ForwardedValues(
                        QueryString=True),
                    LambdaFunctionAssociations=[
                        cloudfront.LambdaFunctionAssociation(
                            EventType="viewer-request",
                            LambdaFunctionARN=refresh_auth_lambda_version.ref(
                            ),
                        )
                    ],
                    TargetOriginId="protected-bucket",
                    ViewerProtocolPolicy="redirect-to-https",
                ),
                cloudfront.CacheBehavior(
                    PathPattern=self.variables["SignOutUrl"],
                    Compress=True,
                    ForwardedValues=cloudfront.ForwardedValues(
                        QueryString=True),
                    LambdaFunctionAssociations=[
                        cloudfront.LambdaFunctionAssociation(
                            EventType="viewer-request",
                            LambdaFunctionARN=sign_out_lambda_version.ref(),
                        )
                    ],
                    TargetOriginId="protected-bucket",
                    ViewerProtocolPolicy="redirect-to-https",
                ),
            ],
            "DefaultCacheBehavior":
            cloudfront.DefaultCacheBehavior(
                AllowedMethods=["GET", "HEAD"],
                Compress=True,
                DefaultTTL="86400",
                ForwardedValues=cloudfront.ForwardedValues(QueryString=True),
                LambdaFunctionAssociations=default_cache_behavior_lambdas,
                TargetOriginId="protected-bucket",
                ViewerProtocolPolicy="redirect-to-https",
            ),
            "DefaultRootObject":
            "index.html",
            "Logging":
            self.add_logging_bucket(),
            "PriceClass":
            self.variables["PriceClass"],
            "Enabled":
            True,
            "WebACLId":
            self.add_web_acl(),
            "CustomErrorResponses":
            self._get_error_responses(),
            "ViewerCertificate":
            self.add_acm_cert(),
        }
Example #11
0
    def __init__(self, title, key, **kwargs):
        super().__init__(title, **kwargs)

        name = self.title
        if 'AllowedMethods' in key:
            self.AllowedMethods = get_endvalue(f'{name}AllowedMethods')

        if 'CachedMethods' in key:
            self.CachedMethods = get_endvalue(f'{name}CachedMethods')

        # If not defined default to True
        if 'Compress' in key:
            self.Compress = get_endvalue(f'{name}Compress')
        else:
            self.Compress = True

        if 'DefaultTTL' in key:
            self.DefaultTTL = get_endvalue(f'{name}DefaultTTL')

        self.ForwardedValues = clf.ForwardedValues()
        # If not defined default to True
        if 'QueryString' in key:
            self.ForwardedValues.QueryString = get_endvalue(
                f'{name}QueryString')
        else:
            self.ForwardedValues.QueryString = True

        if 'CookiesForward' in key:
            self.ForwardedValues.Cookies = clf.Cookies(
                Forward=get_endvalue(f'{name}CookiesForward'))
            if 'CookiesWhitelistedNames' in key:
                self.ForwardedValues.Cookies.WhitelistedNames = (get_endvalue(
                    f'{name}CookiesWhitelistedNames', condition=True))
                # conditions
                c_CookiesForward = get_condition(
                    f'{name}CookiesWhitelistedNames', 'equals', 'whitelist',
                    f'{name}CookiesForward')

                add_obj(c_CookiesForward)

        # If not defined default to 'Host'
        if 'Headers' in key:
            self.ForwardedValues.Headers = get_endvalue(f'{name}Headers')
        else:
            self.ForwardedValues.Headers = ['Host']

        if 'QueryStringCacheKeys' in key:
            self.ForwardedValues.QueryStringCacheKeys = get_endvalue(
                f'{name}QueryStringCacheKeys', condition=True)
            # conditions
            c_QueryString = get_condition(f'{name}QueryStringCacheKeys',
                                          'equals', True, f'{name}QueryString')

            add_obj(c_QueryString)

        if 'TargetOriginId' in key:
            self.TargetOriginId = get_endvalue(f'{name}TargetOriginId')
        else:
            self.TargetOriginId = If(
                'CloudFrontOriginAdHoc', Ref('RecordSetExternal'),
                Sub('${EnvRole}${RecordSetCloudFrontSuffix}.origin.%s' %
                    cfg.HostedZoneNameEnv))

        if 'MaxTTL' in key:
            self.MaxTTL = get_endvalue(f'{name}MaxTTL')

        if 'MinTTL' in key:
            self.MinTTL = get_endvalue(f'{name}MinTTL')

        if 'LambdaFunctionARN' in key:
            condname = f'{name}LambdaFunctionARN'
            eventType = 'origin-request'
            if 'LambdaEventType' in key:
                eventType = key['LambdaEventType']
            # conditions
            add_obj(get_condition(condname, 'not_equals', 'None'))

            self.LambdaFunctionAssociations = [
                If(
                    condname,
                    clf.LambdaFunctionAssociation(
                        EventType=eventType,
                        LambdaFunctionARN=get_endvalue(condname)),
                    Ref('AWS::NoValue'))
            ]

        if 'ViewerProtocolPolicy' in key:
            self.ViewerProtocolPolicy = get_endvalue(
                f'{name}ViewerProtocolPolicy')
        else:
            self.ViewerProtocolPolicy = 'redirect-to-https'