Exemple #1
0
    def add_cloudfront_distribution(
        self,
        bucket_policy: s3.BucketPolicy,
        cloudfront_distribution_options: Dict[str, Any],
    ) -> cloudfront.Distribution:
        """Add the CloudFront distribution to the template / output the id and domain name.

        Args:
            bucket_policy: Bucket policy to allow CloudFront access.
            cloudfront_distribution_options: The distribution options.

        Return:
            The CloudFront Distribution resource

        """
        distribution = self.template.add_resource(
            cloudfront.Distribution(
                "CFDistribution",
                DependsOn=bucket_policy.title,
                DistributionConfig=cloudfront.DistributionConfig(
                    **cloudfront_distribution_options),
            ))
        self.template.add_output(
            Output(
                "CFDistributionId",
                Description="CloudFront distribution ID",
                Value=distribution.ref(),
            ))
        self.template.add_output(
            Output(
                "CFDistributionDomainName",
                Description="CloudFront distribution domain name",
                Value=distribution.get_att("DomainName"),
            ))
        return distribution
Exemple #2
0
def CF_CloudFront(key):
    for n, v in getattr(cfg, key).items():
        resname = f"{key}{n}"
        # Resources
        R_CloudFrontDistribution = clf.Distribution(resname)

        # process cache_behavior and origin
        cache_behavior_process()
        origin_process()

        # Automatically compute Behaviour Order based on PathPattern
        cfg.dbg_clf_compute_order = {}
        sortedcachebehaviors = sorted(
            cfg.CloudFrontCacheBehaviors.items(),
            key=lambda x_y: clf_compute_order(x_y[1]["PathPattern"]),
        )
        cfg.CloudFrontCacheBehaviors = {x[0]: x[1] for x in sortedcachebehaviors}

        if cfg.debug:
            print("##########CLF_COMPUTE_ORDER#########START#######")
            for n, v in iter(
                sorted(cfg.dbg_clf_compute_order.items(), key=lambda x_y: x_y[1])
            ):
                print(f"{n} {v}\n")
            print("##########CLF_COMPUTE_ORDER#########END#######")

        auto_get_props(R_CloudFrontDistribution)
        add_obj(R_CloudFrontDistribution)
Exemple #3
0
 def create_distribution(self):
     t = self.template
     t.add_resource(
         cf.Distribution(
             DISTRIBUTION,
             DistributionConfig=cf.DistributionConfig(
                 Origins=[
                     cf.Origin(
                         Id='1',
                         DomainName=GetAtt(BUCKET, 'DomainName'),
                         S3OriginConfig=cf.S3Origin(),
                     )
                 ],
                 Enabled=Ref('Enabled'),
                 DefaultCacheBehavior=cf.DefaultCacheBehavior(
                     TargetOriginId='1',
                     ForwardedValues=cf.ForwardedValues(
                         QueryString=False, ),
                     ViewerProtocolPolicy='allow-all',
                 ),
             ),
         ))
     t.add_output(
         Output('DomainName',
                Value=Join('',
                           ['https://',
                            GetAtt(DISTRIBUTION, 'DomainName')])))
Exemple #4
0
    def add_cloudfront_distribution(self, bucket_policy,
                                    cloudfront_distribution_options):
        # type: (s3.BucketPolicy, Dict[str, Any]) -> cloudfront.Distribution
        """Add the CloudFront distribution to the template / output the id and domain name.

        Keyword Args:
            bucket_policy (dict): Bucket policy to allow CloudFront access
            cloudfront_distribution_options (dict): The distribution options

        Return:
            dict: The CloudFront Distribution resource

        """
        distribution = self.template.add_resource(
            cloudfront.Distribution(
                'CFDistribution',
                DependsOn=bucket_policy.title,
                DistributionConfig=cloudfront.DistributionConfig(
                    **cloudfront_distribution_options)))
        self.template.add_output(
            Output('CFDistributionId',
                   Description='CloudFront distribution ID',
                   Value=distribution.ref()))
        self.template.add_output(
            Output('CFDistributionDomainName',
                   Description='CloudFront distribution domain name',
                   Value=distribution.get_att('DomainName')))
        return distribution
    def create_distribution(self):
        t = self.template

        s3_origin = cloudfront.Origin(
            DomainName=self.origin_bucket_url,
            Id="s3",
            CustomOriginConfig=cloudfront.CustomOrigin(
                HTTPPort=80,
                HTTPSPort=443,
                OriginProtocolPolicy="http-only"
            ),
        )

        default_behavior = cloudfront.DefaultCacheBehavior(
            AllowedMethods=["GET", "HEAD"],
            CachedMethods=["GET", "HEAD"],
            ViewerProtocolPolicy="redirect-to-https",
            ForwardedValues=cloudfront.ForwardedValues(
                QueryString=True,
                Cookies=cloudfront.Cookies(
                    Forward="none"
                )
            ),
            MinTTL=0,
            MaxTTL=31536000,
            DefaultTTL=86400,
            SmoothStreaming=False,
            TargetOriginId="s3",
        )

        viewer_certificate = NoValue
        if self.certificate_arn:
            viewer_certificate = cloudfront.ViewerCertificate(
                AcmCertificateArn=self.certificate_arn,
                SslSupportMethod="sni-only",
            )

        config = cloudfront.DistributionConfig(
            Aliases=self.aliases,
            DefaultCacheBehavior=default_behavior,
            Comment="%s" % self.origin_bucket_url,
            Enabled=True,
            PriceClass="PriceClass_All",
            ViewerCertificate=viewer_certificate,
            Origins=[s3_origin],
        )

        self.distribution = t.add_resource(
            cloudfront.Distribution(
                "Distribution",
                DistributionConfig=config,
            )
        )

        self.add_output("DistributionId", self.distribution.Ref())
        self.add_output(
            "DomainName",
            self.distribution.GetAtt("DomainName")
        )
    def create_cloudfront_distributions(self):
        blue_tile_distribution = self.add_resource(
            cf.Distribution(
                'tileDistributionBlue',
                DistributionConfig=cf.DistributionConfig(
                    Origins=[
                        cf.Origin(Id='tileOriginId',
                                  DomainName=Join('.', [
                                      'tile-cache',
                                      Ref(self.public_hosted_zone_name)
                                  ]),
                                  CustomOriginConfig=cf.CustomOrigin(
                                      OriginProtocolPolicy='http-only'))
                    ],
                    DefaultCacheBehavior=cf.DefaultCacheBehavior(
                        ForwardedValues=cf.ForwardedValues(QueryString=True),
                        TargetOriginId='tileOriginId',
                        ViewerProtocolPolicy='allow-all'),
                    Enabled=True)))

        green_tile_distribution = self.add_resource(
            cf.Distribution(
                'tileDistributionGreen',
                DistributionConfig=cf.DistributionConfig(
                    Origins=[
                        cf.Origin(Id='tileOriginId',
                                  DomainName=Join('.', [
                                      'tile-cache',
                                      Ref(self.public_hosted_zone_name)
                                  ]),
                                  CustomOriginConfig=cf.CustomOrigin(
                                      OriginProtocolPolicy='http-only'))
                    ],
                    DefaultCacheBehavior=cf.DefaultCacheBehavior(
                        ForwardedValues=cf.ForwardedValues(QueryString=True),
                        TargetOriginId='tileOriginId',
                        ViewerProtocolPolicy='allow-all'),
                    Enabled=True)))

        return blue_tile_distribution, green_tile_distribution
Exemple #7
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",
                ),
            ),
        )
    def __init__(self, title, template, cf_origins_config,
                 cf_cache_behavior_config, cf_distribution_config):
        """
        Class to abstract a Cloudfront Distribution object
        http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cloudfront-distributionconfig.html
        https://github.com/cloudtools/troposphere/blob/master/troposphere/cloudfront.py
        :param title: title of the Cloudfront Distribution and associated resources to be used in cloud formation
        :param template: Troposphere stack to append resources to
        :param cf_origins_config: A list of CFOriginsConfig objects
        :param cf_cache_behavior_config: A list of CFCacheBehavior objects
        :param cf_distribution_config: A CFDistributionConfig object
        """
        self.title = title
        self.origins = []
        self.cache_behaviors = []
        self.default_cache_behavior = cloudfront.DefaultCacheBehavior()

        # Populate origins
        self.add_origins(self.title, cf_origins_config)
        # Populate cache_behaviors
        self.add_cache_behaviors(self.title, cf_cache_behavior_config)

        # Set distribution-wide parameters
        self.cf_dist = cloudfront.DistributionConfig(
            self.title + 'CfDistConfig',
            Aliases=cf_distribution_config.aliases,
            Comment=self.title,
            DefaultCacheBehavior=self.default_cache_behavior,
            CacheBehaviors=self.cache_behaviors,
            DefaultRootObject=cf_distribution_config.default_root_object,
            Enabled=cf_distribution_config.enabled,
            Origins=self.origins,
            PriceClass=cf_distribution_config.price_class)

        if cf_distribution_config.acm_cert_arn:
            self.cf_dist.ViewerCertificate = cloudfront.ViewerCertificate(
                AcmCertificateArn=cf_distribution_config.acm_cert_arn,
                SslSupportMethod='sni-only')

        self.cf_dist = template.add_resource(
            cloudfront.Distribution(title, DistributionConfig=self.cf_dist))
Exemple #9
0
    def build_template(self):

        t = self._init_template()

        dist = t.add_resource(
            cloudfront.Distribution(
                '{}Cloudfront'.format(self.stack_name),
                DistributionConfig=cloudfront.DistributionConfig(
                    Aliases=self.domains,
                    HttpVersion=self.http_version,
                    DefaultRootObject=self.index_file,
                    DefaultCacheBehavior=self.default_behavior,
                    Enabled=True,
                    Origins=[],
                    CacheBehaviors=self.behaviors)))

        if self.acm_ssl_arn:
            dist.DistributionConfig.ViewerCertificate = cloudfront.ViewerCertificate(  # noqa
                AcmCertificateArn=self.acm_ssl_arn,
                SslSupportMethod='sni-only',
                MinimumProtocolVersion='TLSv1.1_2016')
        elif self.iam_ssl_id:
            dist.DistributionConfig.ViewerCertificate = cloudfront.ViewerCertificate(  # noqa
                IamCertificateId=self.iam_ssl_id,
                SslSupportMethod='sni-only',
                MinimumProtocolVersion='TLSv1')

        for o in self.origins:
            dist.DistributionConfig.Origins.append(o.build(t))

        if len(self.errors) > 0:
            dist.DistributionConfig.CustomErrorResponses = self.errors

        t.add_output([
            Output('DistID', Value=Ref(dist)),
            Output('DNS', Value=GetAtt(dist, 'DomainName')),
        ])

        return t
Exemple #10
0
                            'Action': ['s3:GetObject'],
                            'Effect': 'Allow',
                            'Resource': root_bucket_arn,
                            'Principal': '*',
                        }]
                    }))

cdn = template.add_resource(
    cloudfront.Distribution(
        'WebsiteDistribution',
        DistributionConfig=cloudfront.DistributionConfig(
            Aliases=[Ref(domain)],
            Origins=[
                cloudfront.Origin(Id=Ref(root_bucket),
                                  DomainName=GetAtt(root_bucket, 'DomainName'),
                                  S3OriginConfig=cloudfront.S3Origin())
            ],
            DefaultCacheBehavior=cloudfront.DefaultCacheBehavior(
                Compress=True,
                ForwardedValues=cloudfront.ForwardedValues(QueryString=False),
                TargetOriginId=Ref(root_bucket),
                ViewerProtocolPolicy='redirect-to-https'),
            DefaultRootObject=Ref(index_page),
            Enabled=True)))

hosted_zone = Join('', [Ref(zone), '.'])
template.add_resource(
    route53.RecordSetGroup('WebsiteDNSRecord',
                           HostedZoneName=hosted_zone,
                           Comment='Records for the root of the hosted zone',
                           RecordSets=[
                               route53.RecordSet(
Exemple #11
0
 cloudfront.Distribution(
     'FrontendDistribution',
     DistributionConfig=cloudfront.DistributionConfig(
         Aliases=[
             Ref(frontend_cname)
         ],
         CacheBehaviors=[
             cloudfront.CacheBehavior(
                 AllowedMethods=['HEAD', 'GET'],
                 CachedMethods=['HEAD', 'GET'],
                 ForwardedValues=cloudfront.ForwardedValues(
                     QueryString=False
                 ),
                 PathPattern='*',
                 TargetOriginId=Join('-', ['S3', Ref(frontend_bucket)]),
                 ViewerProtocolPolicy='redirect-to-https'
             )
         ],
         CustomErrorResponses=[
             cloudfront.CustomErrorResponse(
                 ErrorCode=404,
                 ResponseCode=200,
                 ResponsePagePath='/index.html'
             )
         ],
         DefaultCacheBehavior=cloudfront.DefaultCacheBehavior(
             ForwardedValues=cloudfront.ForwardedValues(
                 QueryString=False
             ),
             TargetOriginId=Join('-', ['S3', Ref(frontend_bucket)]),
             ViewerProtocolPolicy='redirect-to-https'
         ),
         DefaultRootObject='index.html',
         Enabled=True,
         IPV6Enabled=True,
         Origins=[
             cloudfront.Origin(
                 DomainName=GetAtt(frontend_bucket, 'DomainName'),
                 Id=Join('-', ['S3', Ref(frontend_bucket)]),
                 S3OriginConfig=cloudfront.S3Origin()
             )
         ],
         ViewerCertificate=cloudfront.ViewerCertificate(
             AcmCertificateArn=Ref(frontend_ssl),
             SslSupportMethod='sni-only'
         )
     )
 )
Exemple #12
0
    cloudfront.Distribution(
        "CloudfrontDistribution",
        DistributionConfig=cloudfront.DistributionConfig(
            Aliases=[CONFIG['DOMAIN_NAME']],
            Origins=[
                cloudfront.Origin(
                    Id="Origin 1",

                    # turn `http://mybucket.s3-website-us-east-1.amazonaws.com/`y
                    # into `mybucket.s3-website-us-east-1.amazonaws.com`
                    DomainName=Select(
                        2,
                        Split("/",
                              GetAtt(StaticHostingPublicBucket,
                                     'WebsiteURL'))),

                    # S3 website hosting only serves on 80
                    CustomOriginConfig=cloudfront.CustomOriginConfig(
                        HTTPPort=80,
                        OriginProtocolPolicy='http-only',
                    ))
            ],
            ViewerCertificate=cloudfront.ViewerCertificate(
                AcmCertificateArn=Ref(CloudFrontCertificate),
                SslSupportMethod='sni-only',
            ),
            DefaultCacheBehavior=cloudfront.DefaultCacheBehavior(
                TargetOriginId="Origin 1",
                ForwardedValues=cloudfront.ForwardedValues(QueryString=False),
                ViewerProtocolPolicy="redirect-to-https",
                AllowedMethods=["GET", "HEAD"],
                DefaultTTL=86400  # one day
            ),
            DefaultRootObject='index.html',
            Enabled=True,
            HttpVersion='http2',
            # Logging=cloudfront.Logging(
            #     Bucket=GetAtt(CloudfrontLogBucket, 'DomainName'),
            #     IncludeCookies=False
            # ),
            PriceClass='PriceClass_100',
        ),
        Tags=Tags(**shared_tags_args)))
Exemple #13
0
cloudfront_distribution = stack.add_resource(cloudfront.Distribution(
    'visibilitycloudfront',
    DistributionConfig=cloudfront.DistributionConfig(
        WebACLId=Ref(waf),
        Origins=[
            cloudfront.Origin(
                Id='apiv1',
                DomainName='applicationelasticlb-208988572.us-east-1.elb.amazonaws.com',
                CustomOriginConfig=cloudfront.CustomOrigin(
                    HTTPPort="80",
                    OriginProtocolPolicy="http-only",
                ),
            ),
            cloudfront.Origin(
                Id='staticv1',
                DomainName='cihackathon.s3.amazonaws.com',
                S3OriginConfig=cloudfront.S3Origin(),
            ),
        ],
        DefaultCacheBehavior=cloudfront.DefaultCacheBehavior(
            TargetOriginId="staticv1",
            ForwardedValues=cloudfront.ForwardedValues(
                QueryString=False,
            ),
            ViewerProtocolPolicy="allow-all",
            MinTTL=1,
            MaxTTL=60,
        ),
        CacheBehaviors=[
            cloudfront.CacheBehavior(
                TargetOriginId='apiv1',
                ForwardedValues=cloudfront.ForwardedValues(
                    QueryString=True,
                ),
                ViewerProtocolPolicy="allow-all",
                MinTTL=1,
                MaxTTL=60,
                PathPattern='/api/v1/*',
            ),
        ],
        Enabled=True,
        HttpVersion='http1.1',
    ),
))
Exemple #14
0
            )
        )

        if "cloudfront" in bucket:
            cloudfrontBucket = f"{bucket.lower()}-{randomPrefix}"

    cloudfront = t.add_resource(
        cloudfront.Distribution(
            "Cloudfront",
            DistributionConfig=cloudfront.DistributionConfig(
                Origins=[
                    cloudfront.Origin(
                        Id="1",
                        DomainName=f"{cloudfrontBucket}.s3-ap-southeast-2.amazonaws.com",
                        S3OriginConfig=cloudfront.S3OriginConfig(),
                    )
                ],
                DefaultCacheBehavior=cloudfront.DefaultCacheBehavior(
                    TargetOriginId="1",
                    ForwardedValues=cloudfront.ForwardedValues(QueryString=False),
                    ViewerProtocolPolicy="allow-all",
                ),
                Enabled=True,
                HttpVersion="http2",
            ),
        )
    )

    with open("template.yml", "w") as file:
        file.write(t.to_yaml())
Exemple #15
0
    def create_template(self):
        """Create template (main function called by Stacker)."""
        template = self.template
        variables = self.get_variables()
        template.add_version('2010-09-09')
        template.add_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()))

        cfdistribution = template.add_resource(
            cloudfront.Distribution(
                'CFDistribution',
                DependsOn=allowcfaccess.title,
                DistributionConfig=cloudfront.DistributionConfig(
                    Aliases=If('AliasesSpecified', variables['Aliases'].ref,
                               NoValue),
                    Origins=[
                        cloudfront.Origin(
                            DomainName=Join(
                                '.', [bucket.ref(), 's3.amazonaws.com']),
                            S3OriginConfig=cloudfront.S3Origin(
                                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=If(
                            'DirectoryIndexSpecified',
                            [
                                cloudfront.LambdaFunctionAssociation(
                                    EventType='origin-request',
                                    LambdaFunctionARN=cfdirectoryindexrewritever
                                    .ref()  # noqa
                                )
                            ],
                            NoValue),
                        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')))
Exemple #16
0
    def create_cloudfront_distributions(self):
        blue_tile_distribution = self.add_resource(
            cf.Distribution(
                'tileDistributionBlue',
                DistributionConfig=cf.DistributionConfig(
                    Origins=[
                        cf.Origin(Id='tileOriginId',
                                  DomainName=Join('.', [
                                      'blue-tiles',
                                      Ref(self.public_hosted_zone_name)
                                  ]),
                                  CustomOriginConfig=cf.CustomOrigin(
                                      OriginProtocolPolicy='http-only'))
                    ],
                    DefaultCacheBehavior=cf.DefaultCacheBehavior(
                        ForwardedValues=cf.ForwardedValues(QueryString=True),
                        TargetOriginId='tileOriginId',
                        ViewerProtocolPolicy='allow-all'),
                    Enabled=True)))

        self.add_resource(
            cw.Alarm('alarmTileDistributionBlueOrigin4XX',
                     AlarmDescription='Tile distribution origin 4XXs',
                     AlarmActions=[Ref(self.notification_topic_arn)],
                     Statistic='Average',
                     Period=300,
                     Threshold='20',
                     EvaluationPeriods=1,
                     ComparisonOperator='GreaterThanThreshold',
                     MetricName='4xxErrorRate',
                     Namespace='AWS/CloudFront',
                     Dimensions=[
                         cw.MetricDimension('metricDistributionId',
                                            Name='DistributionId',
                                            Value=Ref(blue_tile_distribution)),
                         cw.MetricDimension('metricRegion',
                                            Name='Region',
                                            Value='Global')
                     ]))

        self.add_resource(
            cw.Alarm('alarmTileDistributionBlueOrigin5XX',
                     AlarmDescription='Tile distribution origin 5XXs',
                     AlarmActions=[Ref(self.notification_topic_arn)],
                     Statistic='Average',
                     Period=60,
                     Threshold='0',
                     EvaluationPeriods=1,
                     ComparisonOperator='GreaterThanThreshold',
                     MetricName='5xxErrorRate',
                     Namespace='AWS/CloudFront',
                     Dimensions=[
                         cw.MetricDimension('metricDistributionId',
                                            Name='DistributionId',
                                            Value=Ref(blue_tile_distribution)),
                         cw.MetricDimension('metricRegion',
                                            Name='Region',
                                            Value='Global')
                     ]))

        green_tile_distribution = self.add_resource(
            cf.Distribution(
                'tileDistributionGreen',
                DistributionConfig=cf.DistributionConfig(
                    Origins=[
                        cf.Origin(Id='tileOriginId',
                                  DomainName=Join('.', [
                                      'green-tiles',
                                      Ref(self.public_hosted_zone_name)
                                  ]),
                                  CustomOriginConfig=cf.CustomOrigin(
                                      OriginProtocolPolicy='http-only'))
                    ],
                    DefaultCacheBehavior=cf.DefaultCacheBehavior(
                        ForwardedValues=cf.ForwardedValues(QueryString=True),
                        TargetOriginId='tileOriginId',
                        ViewerProtocolPolicy='allow-all'),
                    Enabled=True)))

        self.add_resource(
            cw.Alarm('alarmTileDistributionGreenOrigin4XX',
                     AlarmDescription='Tile distribution origin 4XXs',
                     AlarmActions=[Ref(self.notification_topic_arn)],
                     Statistic='Average',
                     Period=300,
                     Threshold='20',
                     EvaluationPeriods=1,
                     ComparisonOperator='GreaterThanThreshold',
                     MetricName='4xxErrorRate',
                     Namespace='AWS/CloudFront',
                     Dimensions=[
                         cw.MetricDimension(
                             'metricDistributionId',
                             Name='DistributionId',
                             Value=Ref(green_tile_distribution)),
                         cw.MetricDimension('metricRegion',
                                            Name='Region',
                                            Value='Global')
                     ]))

        self.add_resource(
            cw.Alarm('alarmTileDistributionGreenOrigin5XX',
                     AlarmDescription='Tile distribution origin 5XXs',
                     AlarmActions=[Ref(self.notification_topic_arn)],
                     Statistic='Average',
                     Period=60,
                     Threshold='0',
                     EvaluationPeriods=1,
                     ComparisonOperator='GreaterThanThreshold',
                     MetricName='5xxErrorRate',
                     Namespace='AWS/CloudFront',
                     Dimensions=[
                         cw.MetricDimension(
                             'metricDistributionId',
                             Name='DistributionId',
                             Value=Ref(green_tile_distribution)),
                         cw.MetricDimension('metricRegion',
                                            Name='Region',
                                            Value='Global')
                     ]))

        return blue_tile_distribution, green_tile_distribution
    def cloudfront_distribution(self):
        if self.vars["AcmCertificateARN"]:
            viewer_certificate = cf.ViewerCertificate(
                SslSupportMethod="sni-only",
                MinimumProtocolVersion="TLSv1",
                AcmCertificateArn=self.vars["AcmCertificateARN"],
            )
            url_prefix = 'https://'
        else:
            viewer_certificate = NoValue
            url_prefix = 'http://'

        t = self.template
        self.SiteCFDistribution = t.add_resource(
            cf.Distribution(
                "SiteCFDistribution",
                DistributionConfig=cf.DistributionConfig(
                    Comment="S3 Distribution",
                    Logging=cf.Logging(
                        Prefix=self.vars["FQDNPublic"] + "/cloudfront_logs/",
                        Bucket=self.vars["LogBucket"] + ".s3.amazonaws.com",
                        IncludeCookies="false"),
                    WebACLId=self.vars["WebACLId"],
                    Origins=[
                        cf.Origin(
                            S3OriginConfig=cf.S3Origin(OriginAccessIdentity=(
                                "origin-access-identity/cloudfront/" +
                                self.vars["OriginAccessIdentity"]), ),
                            Id="myS3Origin",
                            DomainName=GetAtt(self.SiteBucket, "DomainName"),
                            OriginPath=self.vars["OriginPath"],
                        )
                    ],
                    DefaultRootObject=self.vars["DefaultRootObject"],
                    PriceClass="PriceClass_100",
                    Enabled="true",
                    DefaultCacheBehavior=cf.DefaultCacheBehavior(
                        ViewerProtocolPolicy="redirect-to-https",
                        ForwardedValues=cf.ForwardedValues(
                            Cookies=cf.Cookies(Forward="none"),
                            QueryString="true"),
                        TargetOriginId="myS3Origin",
                        DefaultTTL=self.vars["DefaultTTL"],
                    ),
                    Aliases=[self.vars["FQDNPublic"]],
                    ViewerCertificate=viewer_certificate,
                ),
            ))

        CloudFrontDistribution = t.add_output(
            Output(
                "CloudFrontDistribution",
                Description="Cloudfront distribution domainname in AWS",
                Value=GetAtt(self.SiteCFDistribution, "DomainName"),
            ))
        WebsiteURL = t.add_output(
            Output(
                "WebsiteURL",
                Description="Public URL of cloudfront hosted website",
                Value=url_prefix + self.vars["FQDNPublic"],
            ))
Exemple #18
0
    def __init__(self):
        # Resources
        CloudFrontDistribution = clf.Distribution('CloudFrontDistribution')

        DistributionConfig = CFDistributionConfig()

        cachebehaviors = []
        sortedcachebehaviors = sorted(
            iter(cfg.CloudFrontCacheBehaviors.items()),
            key=lambda x_y: (
                (x_y[1]['Order'] * 1000) - len(x_y[1]['PathPattern'])
                if 'PathPattern' in x_y[1] else 0)
            if 'Order' in x_y[1] else x_y[0])
        itercachebehaviors = iter(sortedcachebehaviors)
        next(itercachebehaviors)
        for n, v in itercachebehaviors:
            if not v['PathPattern']:
                continue
            name = f'CloudFrontCacheBehaviors{n}'

            cachebehavior = CFCacheBehavior(name, key=v)

            # Create and Use Condition
            # only if PathPattern Value differ between envs
            if f'{name}PathPattern' not in cfg.fixedvalues:
                # conditions
                add_obj(
                    get_condition(name, 'not_equals', 'None',
                                  f'{name}PathPattern'))

                cachebehaviors.append(
                    If(name, cachebehavior, Ref("AWS::NoValue")))
            else:
                cachebehaviors.append(cachebehavior)

        DistributionConfig.CacheBehaviors = cachebehaviors

        cloudfrontaliasextra = []
        for n in cfg.CloudFrontAliasExtra:
            name = f'CloudFrontAliasExtra{n}'

            # parameters
            p_Alias = Parameter(name)
            p_Alias.Description = ('Alias extra - '
                                   'empty for default based on env/role')

            add_obj(p_Alias)

            cloudfrontaliasextra.append(get_endvalue(name, condition=True))

            # conditions
            add_obj(get_condition(name, 'not_equals', 'None'))

        DistributionConfig.Aliases = cloudfrontaliasextra
        CloudFrontDistribution.DistributionConfig = DistributionConfig

        Origins = []
        try:
            cfg.CloudFrontOrigins
        except:
            pass
        else:
            for n, v in cfg.CloudFrontOrigins.items():
                name = f'CloudFrontOrigins{n}'

                # parameters
                p_Origin = Parameter(f'CloudFrontOrigins{n}DomainName')
                p_Origin.Description = (
                    'Origin - empty for default based on env/role')

                p_OriginHTTPSPort = Parameter(f'CloudFrontOrigins{n}HTTPSPort')
                p_OriginHTTPSPort.Description = (
                    'Origin - empty for default based on env/role')

                if 'OriginAccessIdentity' in v:
                    p_OriginAccessIdentity = Parameter(
                        f'CloudFrontOrigins{n}OriginAccessIdentity')
                    p_OriginAccessIdentity.Description = (
                        'OriginAccessIdentity - '
                        'empty for default based on env/role')

                    add_obj(p_OriginAccessIdentity)

                add_obj([
                    p_Origin,
                    p_OriginHTTPSPort,
                ])

                Origin = CFOriginCLF(name, index=n)
                Origins.append(Origin)

        CloudFrontDistribution.DistributionConfig.Origins = Origins
        CloudFrontDistribution.DistributionConfig.Comment = get_endvalue(
            'CloudFrontComment')

        R_CloudFrontDistribution = CloudFrontDistribution

        add_obj([
            R_CloudFrontDistribution,
        ])

        self.CloudFrontDistribution = CloudFrontDistribution
Exemple #19
0
 cloudfront.Distribution(
     "ExampleDistribution",
     Condition=use_cert_cond,
     DistributionConfig=cloudfront.DistributionConfig(
         Comment="Example distribution for restricted access",
         Aliases=[domain_name],
         Enabled=True,
         IPV6Enabled=True,
         HttpVersion='http2',
         PriceClass='PriceClass_100',
         Origins=[
             # Your usual config goes here, example:
             cloudfront.Origin(
                 Id="ExampleS3",
                 DomainName=Join(
                     '', [Ref(example_bucket), '.s3.amazonaws.com']),
                 S3OriginConfig=cloudfront.S3OriginConfig(
                     OriginAccessIdentity=Join('', [
                         'origin-access-identity/cloudfront/',
                         Ref(example_bucket_oai),
                     ])),
             ),
         ],
         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',
         ),
     ),
     Tags=GetAtt(cloudformation_tags, 'TagList'),
 ))
Exemple #20
0
    def create_template(self):
        """Create template (main function called by Stacker)."""
        template = self.template
        variables = self.get_variables()
        template.add_version('2010-09-09')
        template.add_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(
            '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=Policy(
                    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'), '/*'])])
                    ])))

        cfdistribution = template.add_resource(
            cloudfront.Distribution(
                'CFDistribution',
                DependsOn=allowcfaccess.title,
                DistributionConfig=cloudfront.DistributionConfig(
                    Aliases=If('AliasesSpecified', variables['Aliases'].ref,
                               NoValue),
                    Origins=[
                        cloudfront.Origin(
                            DomainName=Join(
                                '.', [bucket.ref(), 's3.amazonaws.com']),
                            S3OriginConfig=cloudfront.S3Origin(
                                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,
                        ),
                        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')))
Exemple #21
0
 cloudfront.Distribution(
     'Distribution',
     DistributionConfig=cloudfront.DistributionConfig(
         Aliases=[Ref(domain)],
         CacheBehaviors=[
             cloudfront.CacheBehavior(
                 Compress=True,
                 ForwardedValues=cloudfront.ForwardedValues(
                     Cookies=cloudfront.Cookies(Forward='none'),
                     QueryString=False,
                 ),
                 PathPattern=Ref(media_pattern),
                 TargetOriginId=Sub(
                     '${domain}${path}', **{
                         'domain': Ref(media_domain),
                         'path': Ref(media_path)
                     }),
                 ViewerProtocolPolicy='redirect-to-https',
             )
         ],
         Comment=Sub('${AWS::StackName}'),
         DefaultCacheBehavior=cloudfront.DefaultCacheBehavior(
             Compress=True,
             ForwardedValues=cloudfront.ForwardedValues(
                 Cookies=cloudfront.Cookies(Forward='none'),
                 QueryString=False,
             ),
             TargetOriginId=Sub(
                 '${domain}${path}', **{
                     'domain': Ref(static_domain),
                     'path': Ref(static_path)
                 }),
             ViewerProtocolPolicy='redirect-to-https',
         ),
         Enabled=True,
         Origins=[
             cloudfront.Origin(
                 Id=Sub(
                     '${domain}${path}', **{
                         'domain': Ref(static_domain),
                         'path': Ref(static_path)
                     }),
                 DomainName=Ref(static_domain),
                 OriginPath=Ref(static_path),
                 CustomOriginConfig=cloudfront.CustomOrigin(
                     OriginProtocolPolicy='https-only'),
             ),
             cloudfront.Origin(
                 Id=Sub(
                     '${domain}${path}', **{
                         'domain': Ref(media_domain),
                         'path': Ref(media_path)
                     }),
                 DomainName=Ref(media_domain),
                 OriginPath=Ref(media_path),
                 CustomOriginConfig=cloudfront.CustomOrigin(
                     OriginProtocolPolicy='https-only'),
             ),
         ],
         PriceClass='PriceClass_100',
         ViewerCertificate=cloudfront.ViewerCertificate(
             AcmCertificateArn=Ref(certificate),
             SslSupportMethod='sni-only',
         ))))
Exemple #22
0
 cf.Distribution(
     'cdnDistribution{}'.format(src_domain.replace('.', '0')),
     DependsOn='cdnCertificate{}'.format(src_domain.replace('.', '0')),
     DistributionConfig=cf.DistributionConfig(
         Comment='{} - {}'.format(env, cdn_domain),
         Enabled=True,
         PriceClass='PriceClass_All',
         HttpVersion='http2',
         Origins=[
             cdnOrigin,
         ],
         Aliases=[cdn_domain, alternate_name],
         ViewerCertificate=cf.ViewerCertificate(
             AcmCertificateArn=Ref(cdnCertificate),
             SslSupportMethod='sni-only',
             MinimumProtocolVersion='TLSv1.2_2018',
         ),
         DefaultCacheBehavior=cf.DefaultCacheBehavior(
             AllowedMethods=['GET', 'HEAD', 'OPTIONS'],
             CachedMethods=['GET', 'HEAD'],
             ViewerProtocolPolicy='redirect-to-https',
             TargetOriginId='{}-{}-{}'.format(env_l, app_group_l,
                                              src_domain),
             ForwardedValues=cf.ForwardedValues(
                 Headers=["Accept-Encoding"],
                 QueryString=True,
             ),
             MinTTL=0,
             MaxTTL=int(max_ttl[0]),
             DefaultTTL=int(default_ttl[0]),
             SmoothStreaming=False,
             Compress=True),
         CustomErrorResponses=[
             cf.CustomErrorResponse(
                 ErrorCachingMinTTL='0',
                 ErrorCode='403',
             ),
             cf.CustomErrorResponse(
                 ErrorCachingMinTTL='0',
                 ErrorCode='404',
             ),
             cf.CustomErrorResponse(
                 ErrorCachingMinTTL='0',
                 ErrorCode='500',
             ),
             cf.CustomErrorResponse(
                 ErrorCachingMinTTL='0',
                 ErrorCode='501',
             ),
             cf.CustomErrorResponse(
                 ErrorCachingMinTTL='0',
                 ErrorCode='502',
             ),
             cf.CustomErrorResponse(
                 ErrorCachingMinTTL='0',
                 ErrorCode='503',
             ),
             cf.CustomErrorResponse(
                 ErrorCachingMinTTL='0',
                 ErrorCode='504',
             ),
         ],
     ),
     Tags=DefaultTags))
Exemple #23
0
def render_cloudfront(context, template, origin_hostname):
    if not context['cloudfront']['origins']:
        ensure(
            context['full_hostname'],
            "A public hostname is required to be pointed at by the Cloudfront CDN"
        )

    allowed_cnames = context['cloudfront']['subdomains'] + context[
        'cloudfront']['subdomains-without-dns']

    def _cookies(cookies):
        if cookies:
            return cloudfront.Cookies(Forward='whitelist',
                                      WhitelistedNames=cookies)
        return cloudfront.Cookies(Forward='none')

    if context['cloudfront']['origins']:
        origins = [
            cloudfront.Origin(DomainName=o['hostname'],
                              Id=o_id,
                              CustomOriginConfig=cloudfront.CustomOrigin(
                                  HTTPSPort=443,
                                  OriginProtocolPolicy='https-only'))
            for o_id, o in context['cloudfront']['origins'].items()
        ]
        origin = origins[0].Id
    else:
        origin = CLOUDFRONT_TITLE + 'Origin'
        origins = [
            cloudfront.Origin(DomainName=origin_hostname,
                              Id=origin,
                              CustomOriginConfig=cloudfront.CustomOrigin(
                                  HTTPSPort=443,
                                  OriginProtocolPolicy='https-only'))
        ]
    props = {
        'Aliases':
        allowed_cnames,
        'CacheBehaviors': [],
        'DefaultCacheBehavior':
        cloudfront.DefaultCacheBehavior(
            AllowedMethods=[
                'DELETE', 'GET', 'HEAD', 'OPTIONS', 'PATCH', 'POST', 'PUT'
            ],
            CachedMethods=['GET', 'HEAD'],
            Compress=context['cloudfront']['compress'],
            DefaultTTL=context['cloudfront']['default-ttl'],
            TargetOriginId=origin,
            ForwardedValues=cloudfront.ForwardedValues(
                Cookies=_cookies(context['cloudfront']['cookies']),
                Headers=context['cloudfront']
                ['headers'],  # 'whitelisted' headers
                QueryString=True),
            ViewerProtocolPolicy='redirect-to-https',
        ),
        'Enabled':
        True,
        'HttpVersion':
        'http2',
        'Origins':
        origins,
        'ViewerCertificate':
        cloudfront.ViewerCertificate(
            IamCertificateId=context['cloudfront']['certificate_id'],
            SslSupportMethod='sni-only')
    }

    def _cache_behavior(origin_id, pattern, headers=None, cookies=None):
        return cloudfront.CacheBehavior(
            TargetOriginId=origin_id,
            DefaultTTL=context['cloudfront']['default-ttl'],
            ForwardedValues=cloudfront.ForwardedValues(
                Cookies=_cookies(cookies),
                QueryString=False,
                Headers=headers if headers else []),
            PathPattern=pattern,
            ViewerProtocolPolicy='allow-all',
        )

    if context['cloudfront']['errors']:
        props['Origins'].append(
            cloudfront.Origin(
                DomainName=context['cloudfront']['errors']['domain'],
                # TODO: constant
                Id=CLOUDFRONT_ERROR_ORIGIN_ID,
                # no advantage in using cloudfront.S3Origin for public buckets
                CustomOriginConfig=cloudfront.CustomOrigin(
                    HTTPSPort=443,
                    OriginProtocolPolicy='https-only'
                    if context['cloudfront']['errors']['protocol'] == 'https'
                    else 'http-only')))
        props['CacheBehaviors'].append(
            _cache_behavior(
                CLOUDFRONT_ERROR_ORIGIN_ID,
                context['cloudfront']['errors']['pattern'],
            ))
        props['CustomErrorResponses'] = [
            cloudfront.CustomErrorResponse(ErrorCode=code,
                                           ResponseCode=code,
                                           ResponsePagePath=page)
            for code, page in context['cloudfront']['errors']['codes'].items()
        ]

    if context['cloudfront']['logging']:
        props['Logging'] = cloudfront.Logging(
            Bucket="%s.s3.amazonaws.com" %
            context['cloudfront']['logging']['bucket'],
            Prefix="%s/" % context['stackname'])

    if context['cloudfront']['origins']:
        props['CacheBehaviors'].extend([
            _cache_behavior(o_id,
                            o['pattern'],
                            headers=o['headers'],
                            cookies=o['cookies'])
            for o_id, o in context['cloudfront']['origins'].items()
            if o['pattern']
        ])

    template.add_resource(
        cloudfront.Distribution(
            CLOUDFRONT_TITLE,
            DistributionConfig=cloudfront.DistributionConfig(**props)))

    for dns in external_dns_cloudfront(context):
        template.add_resource(dns)
Exemple #24
0
 cloudfront.Distribution(
     "ExampleDistribution",
     DistributionConfig=cloudfront.DistributionConfig(
         Comment="Example distribution for restricted access",
         Aliases=[
             Join('.', [Ref(param_label),
                        Ref(param_hosted_zone_name)])
         ],
         Enabled=True,
         IPV6Enabled=True,
         HttpVersion='http2',
         PriceClass='PriceClass_100',
         Origins=[
             cloudfront.Origin(
                 # Your usual config goes here
                 Id="RealOrigin",
                 DomainName="ifconfig.io",
                 CustomOriginConfig=cloudfront.CustomOrigin(
                     HTTPPort=80,
                     HTTPSPort=443,
                     OriginProtocolPolicy='https-only',
                     OriginSSLProtocols=['TLSv1.2', 'TLSv1.1', 'TLSv1']),
             ),
             cloudfront.Origin(
                 # You need to add this origin
                 Id="Authorizer",
                 DomainName=ImportValue(
                     Sub('${' + authorizer_stack.title + '}-domain-name')),
                 CustomOriginConfig=cloudfront.CustomOrigin(
                     HTTPPort=80,
                     HTTPSPort=443,
                     OriginProtocolPolicy='https-only',
                     OriginSSLProtocols=['TLSv1.2', 'TLSv1.1', 'TLSv1']),
             ),
         ],
         CacheBehaviors=[
             cloudfront.CacheBehavior(
                 # The authorizer hijacks a set of URL-paths from your website. All paths are prefixed
                 # with `/auth-<UUID>/`, so they are very unlikely to collide with your content.
                 # Insert this as the first Behaviour.
                 PathPattern=Join('', [
                     ImportValue(
                         Sub('${' + authorizer_stack.title +
                             '}-magic-path')),
                     '/*',
                 ]),
                 ViewerProtocolPolicy='https-only',
                 TargetOriginId='Authorizer',
                 ForwardedValues=cloudfront.ForwardedValues(
                     QueryString=True,
                     Cookies=cloudfront.Cookies(
                         Forward='all',  # Needed to allow Set-Cookie:-headers
                     ),
                 ),
                 MinTTL=0,
                 DefaultTTL=0,
                 MaxTTL=0,
             )
         ],
         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='RealOrigin',
             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=If(use_cert_cond, Ref(acm_cert),
                                  Ref(AWS_NO_VALUE)),
             SslSupportMethod=If(use_cert_cond, 'sni-only',
                                 Ref(AWS_NO_VALUE)),
             CloudFrontDefaultCertificate=If(use_cert_cond,
                                             Ref(AWS_NO_VALUE), True),
         ),
     ),
     Tags=GetAtt(cloudformation_tags, 'TagList'),
 ))