def __init__(self, scope: core.Construct, construct_id: str,
                 **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        # The code that defines your stack goes here
        bucket = s3.Bucket(
            self,
            'cloudfronttestbucket',
            bucket_name="testcloudfrontbuckettoday",
            public_read_access=False,
            removal_policy=core.RemovalPolicy.DESTROY,
        )

        s3identity = cloudfront.OriginAccessIdentity(
            self, 'accessidentity', comment="access-identity-")

        s3Origin = origins.S3Origin(bucket=bucket,
                                    origin_access_identity=s3identity)

        current_behavior = cloudfront.BehaviorOptions(
            origin=s3Origin,
            viewer_protocol_policy=cloudfront.ViewerProtocolPolicy.
            REDIRECT_TO_HTTPS)

        skull_distribution = cloudfront.Distribution(
            self, 'skulldistibution', default_behavior=current_behavior)

        bucket.grant_read(identity=s3identity.grant_principal)
Ejemplo n.º 2
0
    def setup_cloudfront(self):
        """Setup CloudFront
            / is pointing to S3
            /api is pointing to Load Balancer

        Returns
        -------
        aws_cloudfront.Distribution that redirecting traffic to ALB

        """

        return cf.Distribution(
            self,
            'CloudFront',
            default_behavior=cf.BehaviorOptions(
                origin=origins.S3Origin(self.web_bucket)),
            additional_behaviors={
                '/api/*':
                cf.BehaviorOptions(
                    origin=origins.LoadBalancerV2Origin(
                        self.service.load_balancer,
                        protocol_policy=cf.OriginProtocolPolicy.HTTP_ONLY,
                    ),
                    cache_policy=cf.CachePolicy.CACHING_DISABLED,
                    allowed_methods=cf.AllowedMethods.ALLOW_ALL,
                )
            })
Ejemplo n.º 3
0
    def create_cloudfront_for_user_pool(self, tag: str) -> str:
        """
        Creates a CloudFront distribution to sit in front of the Cognito User Pool, to test the
        SDK's ability to specify custom endpoints for a User Pool. Customers may specify custom
        endpoints to (for example) protect unauthorized calls from DDOS attacks that cause accounts
        to be throttled. While that would generally be done by adding a Web Application Firewall in
        front of a CloudFront distribution, we will simply set up a straight-up proxy endpoint to
        ensure that calls are passed through as expected.

        In the future, we may extend this stack and the associated integ tests with an Edge Lambda
        function to inject AppClientSecret after passing through the CloudFront distribution, but
        that is not strictly germane to the simple ability to specify a custom endpoint.

        :return: the CloudFront Origin to be used for the value of the `Endpoint` in the custom
        config
        """
        origin = aws_cloudfront_origins.HttpOrigin(
            f"cognito-idp.{self.region}.amazonaws.com")
        distribution = aws_cloudfront.Distribution(
            self,
            f"cloudfront_userpool_{tag}",
            default_behavior=aws_cloudfront.BehaviorOptions(
                allowed_methods=aws_cloudfront.AllowedMethods.ALLOW_ALL,
                origin=origin),
        )

        return distribution.domain_name
Ejemplo n.º 4
0
 def create_cloud_front(self):
     static_bucket = self.create_s3('static_files', type='s3')
     distribution = cloudfront.Distribution(
         self,
         "distribution",
         default_behavior=cloudfront.BehaviorOptions(
             allowed_methods=cloudfront.AllowedMethods.ALLOW_ALL,
             origin=cloudfront.Origin.from_bucket(static_bucket)))
     # NEED CERTIFICATE, but I don't have one
     # distribution = cloudfront.CloudFrontWebDistribution(
     #     self, "AnAmazingWebsiteProbably",
     #     origin_configs=[cloudfront.SourceConfiguration(
     #         s3_origin_source=cloudfront.S3OriginConfig(
     #             s3_bucket_source=static_bucket),
     #         behaviors=[cloudfront.Behavior(is_default_behavior=True)]
     #     )],
     #     viewer_certificate=cloudfront.ViewerCertificate.from_iam_certificate(
     #         self.CERTIFICATE_ID,
     #         aliases=["example.com"],
     #         security_policy=cloudfront.SecurityPolicyProtocol.TLS_V1,
     #         # default
     #         ssl_method=cloudfront.SSLMethod.SNI
     #     )
     # )
     return distribution
Ejemplo n.º 5
0
    def S3_FRONTENDDEPLOY(self):
        bucket = s3.Bucket(
            self,
            "FrontendBucket",
            removal_policy=core.RemovalPolicy.DESTROY,
            versioned=True,
        )

        distribution = cloudfront.Distribution(
            self,
            "FrontendDistribution",
            # TODO: The domain and cert info should be env vars
            domain_names=["www.seanfischer.io"],
            certificate=certificates.Certificate.from_certificate_arn(
                self,
                "DomainCertificateEast1",
                "arn:aws:acm:us-east-1:261392311630:certificate/859dc9d1-7a5f-4474-bcad-bcba1607a5ed",
            ),
            default_root_object="index.html",
            default_behavior=cloudfront.BehaviorOptions(
                origin=origins.S3Origin(bucket, ),
                viewer_protocol_policy=cloudfront.ViewerProtocolPolicy.
                REDIRECT_TO_HTTPS,
            ),
        )

        s3deploy.BucketDeployment(
            self,
            "FrontendS3Deployment",
            sources=[s3deploy.Source.asset("./src")],
            destination_bucket=bucket,
            distribution=distribution,
        )

        return bucket
Ejemplo n.º 6
0
    def __init__(self, app: core.App, cfn_name: str, stack_env):
        super().__init__(scope=app, id=f"{cfn_name}-{stack_env}")

        s3_bucket = s3.Bucket(scope=self,
                              id=f"{cfn_name}-{stack_env}-bucket",
                              website_index_document="index.html")

        # upload files in `./html` to the bucket defined above
        _ = s3_deploy.BucketDeployment(
            scope=self,
            id=f"{cfn_name}-{stack_env}-deployments",
            sources=[s3_deploy.Source.asset("./html")],
            destination_bucket=s3_bucket,
            destination_key_prefix=self.ORIGIN_PATH)

        # set S3 as origin
        s3_origin = origin.S3Origin(bucket=s3_bucket,
                                    origin_path=self.ORIGIN_PATH)
        # create CloudFront Distribution
        _ = cloud_front.Distribution(
            scope=self,
            id=f"{cfn_name}-{stack_env}",
            default_behavior=cloud_front.BehaviorOptions(
                # may warning here, for type mismatched.
                origin=s3_origin))
def add_distribution(scope: core.Construct, id: str, alb_dns_name: str,
                     port: int, logbucket: s3.IBucket) -> cf.IDistribution:

    load_balancer_arn = core.Fn.get_att(alb_dns_name, "DNSName")
    security_group_id = core.Fn.get_att(alb_dns_name, "SecurityGroups")

    alb2 = alb.ApplicationLoadBalancer.from_application_load_balancer_attributes(
        scope,
        id,
        load_balancer_arn=load_balancer_arn.to_string(),
        security_group_id=security_group_id.to_string(),
        load_balancer_dns_name=alb_dns_name)
    _origin = origins.LoadBalancerV2Origin(
        alb2,
        http_port=port,
        protocol_policy=cf.OriginProtocolPolicy.HTTP_ONLY)
    dist = cf.Distribution(
        scope,
        "CF-" + id,
        default_behavior={
            "origin": _origin,
            "allowed_methods": cf.AllowedMethods.ALLOW_ALL,
            "cache_policy": cf.CachePolicy.CACHING_DISABLED,
            "origin_request_policy": cf.OriginRequestPolicy.ALL_VIEWER,
            "viewer_protocol_policy": cf.ViewerProtocolPolicy.REDIRECT_TO_HTTPS
        },
        minimum_protocol_version=cf.SecurityPolicyProtocol.TLS_V1_2_2019,
        enable_logging=True,
        log_bucket=logbucket)
    return dist.distribution_domain_name
Ejemplo n.º 8
0
    def __init__(self, scope: core.Construct, construct_id: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        # The code that defines your stack goes here
        
        bucket = _s3.Bucket(
            self, '_s3-site-bucket',
            website_index_document='index.html',
            public_read_access=True,
            removal_policy=core.RemovalPolicy.DESTROY
        )
        
        deployment = _deployment.BucketDeployment(
            self, '_s3-asset',
            destination_bucket=bucket,
            sources=[_deployment.Source.asset('./static/')]
        )
        
        cloudfrontorigin = _cloudfront_origins.S3Origin(
            bucket,
        )
        
        cloudfront = _cloudfront.Distribution(
            self, 'cloudfront_dist',
            default_behavior=cloudfrontorigin
        )
        
        core.CfnOutput(self, 'Cloudfront-DomainName', value=cloudfront.distribution_domain_name)
Ejemplo n.º 9
0
    def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        lambda_edge = _lambda.Function(
            self,
            'LambdaEdge',
            runtime=_lambda.Runtime.PYTHON_3_7,
            handler='index.handler',
            code=_lambda.Code.from_asset('lambda'),
        )

        #create an S3 bucket used as origin for Cloudfront, not used but origin is a required field
        hosting_bucket = s3.Bucket(self, "MyHostingBucket")

        my_distribution = cloudfront.Distribution(
            self,
            "MyDistribution",
            default_behavior=cloudfront.BehaviorOptions(
                origin=origins.S3Origin(hosting_bucket),
                edge_lambdas=[
                    cloudfront.EdgeLambda(
                        function_version=lambda_edge.current_version,
                        event_type=cloudfront.LambdaEdgeEventType.
                        ORIGIN_REQUEST)
                ]),
            comment='Dynamic content generation using Lambda@Edge')

        CfnOutput(self,
                  "DomainName",
                  value=my_distribution.domain_name,
                  export_name='DomainName',
                  description='CloudFront Domain Name')
    def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        # The code that defines your stack goes here

        vpc = ec2.Vpc(
            self,
            "MyVpc",
            max_azs=3,
        )

        cluster = ecs.Cluster(self, 'Ec2Cluster', vpc=vpc)

        fargate_service = ecs_patterns.ApplicationLoadBalancedFargateService(
            self,
            "FargateService",
            cluster=cluster,
            cpu=256,
            desired_count=1,
            task_image_options=ecs_patterns.
            ApplicationLoadBalancedTaskImageOptions(
                image=ecs.ContainerImage.from_asset(
                    os.path.join(dirname, "..", "image")),
                container_port=3000),
            memory_limit_mib=512,
            public_load_balancer=True,
            listener_port=80)

        fargate_service.service.connections.security_groups[
            0].add_ingress_rule(peer=ec2.Peer.ipv4(vpc.vpc_cidr_block),
                                connection=ec2.Port.tcp(80),
                                description="Allow http inbound from VPC")

        fargate_service.target_group.configure_health_check(path="/login")

        distribution = cloudfront.Distribution(
            self,
            "myDist",
            default_behavior={
                "origin":
                origins.LoadBalancerV2Origin(
                    fargate_service.load_balancer,
                    protocol_policy=cloudfront.OriginProtocolPolicy(
                        "HTTP_ONLY"))
            })

        core.CfnOutput(
            self,
            "LoadBalancerDNS",
            value=fargate_service.load_balancer.load_balancer_dns_name)

        core.CfnOutput(self,
                       "CloudFrontDistributionDNS",
                       value=distribution.domain_name)
Ejemplo n.º 11
0
 def _create_cloudfront_distribution(self):
     """Create a cloudfront distribution with a private bucket as the origin"""
     self.distribution = cloudfront.Distribution(
         self,
         "cloudfront_distribution",
         default_behavior=cloudfront.BehaviorOptions(
             origin=origins.S3Origin(self.bucket),
             viewer_protocol_policy=cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
         ),
         domain_names=[self._site_domain_name],
         certificate=self.certificate,
         default_root_object="index.html",
     )
Ejemplo n.º 12
0
  def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
    super().__init__(scope, construct_id, **kwargs)

    s3_bucket_name = cdk.CfnParameter(self, 'S3BucketForStaticContents',
      type='String',
      description='s3 bucket that the site contents are deployed to'
    )

    site_bucket = s3.Bucket.from_bucket_name(self, 'S3BucketForStaticSite', s3_bucket_name.value_as_string)

    cloudfrontOAI = cloudfront.OriginAccessIdentity(self, 'CloudFrontOAI',
      comment="Allows CloudFront to reach the bucket: {name}".format(name=s3_bucket_name.value_as_string)
    );
    cloudfrontOAI.apply_removal_policy(cdk.RemovalPolicy.DESTROY)

    #XXX: Add policy document the existing s3 bucket
    #XXX: https://stackoverflow.com/questions/60087302/how-to-add-resource-policy-to-existing-s3-bucket-with-cdk-in-javascript
    site_bucket_policy_statement = aws_iam.PolicyStatement(**{
      'actions': ['s3:GetObject'],
      'resources': [site_bucket.arn_for_objects('*')],
      'principals': [aws_iam.CanonicalUserPrincipal(cloudfrontOAI.cloud_front_origin_access_identity_s3_canonical_user_id)]
    })

    s3.CfnBucketPolicy(self, 'SiteBucketPolicy',
      bucket=site_bucket.bucket_name,
      policy_document=aws_iam.PolicyDocument(statements=[site_bucket_policy_statement])
    )

    distribution = cloudfront.Distribution(self, "myDist",
      default_behavior=cloudfront.BehaviorOptions(
        origin=cf_origins.S3Origin(bucket=site_bucket, origin_access_identity=cloudfrontOAI)
      ),
      error_responses=[
        #XXX: If you have accessed root page of cloudfront url (i.e. https://your-domain.cloudfront.net/),
        #XXX: 403:Forbidden error might occur. In order to prevent this error,
        #XXX: configure 403:Forbidden error response page to be 'index.html'
        cloudfront.ErrorResponse(http_status=403, response_http_status=200,
          response_page_path='/index.html', ttl=cdk.Duration.seconds(10)),
        #XXX: Configure 404:NotFound error response page to be 'error.html'
        cloudfront.ErrorResponse(http_status=404, response_http_status=404,
          response_page_path='/error.html', ttl=cdk.Duration.seconds(10))
      ]
    )

    cdk.CfnOutput(self, 'StackName', value=self.stack_name, export_name='StackName')
    cdk.CfnOutput(self, 'SiteBucket', value=site_bucket.bucket_name, export_name='SiteBucket')
    cdk.CfnOutput(self, 'DistributionId', value=distribution.distribution_id, export_name='DistributionId')
    cdk.CfnOutput(self, 'DistributionDomainName', value=distribution.distribution_domain_name, export_name='DistributionDomainName')
    cdk.CfnOutput(self, 'CloudFrontOriginAccessId', value=cloudfrontOAI.cloud_front_origin_access_identity_s3_canonical_user_id, export_name='CloudFrontOAI')
 def __create_cloud_front_www(
     self, origin_bucket_name: str, domain_name: str,
     alternative_domain_names: Optional[List[str]],
     ssl_certificate: aws_certificatemanager.Certificate,
     cache_policy: aws_cloudfront.CachePolicy,
     origin_access_identity: aws_cloudfront.OriginAccessIdentity,
     edge_lambda_viewer_request: aws_lambda.Version
 ) -> aws_cloudfront.Distribution:
     domain_names = alternative_domain_names if alternative_domain_names else []
     domain_names.append(domain_name)
     domain_names = set(domain_names)
     return aws_cloudfront.Distribution(
         self,
         'CloudFrontWWW',
         enabled=True,
         certificate=ssl_certificate,
         comment='CloudFront Distribution for your WWW static website',
         domain_names=list(domain_names),
         http_version=HttpVersion.HTTP2,
         price_class=PriceClass.PRICE_CLASS_100,
         default_behavior=BehaviorOptions(
             allowed_methods=AllowedMethods.ALLOW_GET_HEAD,
             cached_methods=CachedMethods.CACHE_GET_HEAD,
             cache_policy=cache_policy,
             viewer_protocol_policy=ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
             origin=aws_cloudfront_origins.S3Origin(
                 bucket=Bucket.from_bucket_name(
                     self, "OriginProd", bucket_name=origin_bucket_name),
                 origin_access_identity=origin_access_identity,
                 origin_path='/src/prod'),
             edge_lambdas=[
                 EdgeLambda(event_type=LambdaEdgeEventType.VIEWER_REQUEST,
                            include_body=False,
                            function_version=edge_lambda_viewer_request)
             ]),
         error_responses=[
             ErrorResponse(ttl=Duration.seconds(300),
                           response_page_path='/404.html',
                           http_status=403,
                           response_http_status=404)
         ])
Ejemplo n.º 14
0
    def __init__(self, scope: core.Construct, construct_id: str,
                 s3_construct: S3Construct, **kwargs) -> None:

        super().__init__(scope, construct_id, **kwargs)

        self.distribution = aws_cloudfront.Distribution(
            self,
            "release_artifacts_cloudfront",
            default_behavior=aws_cloudfront.BehaviorOptions(
                origin=aws_cloudfront_origins.S3Origin(s3_construct.bucket),
                viewer_protocol_policy=aws_cloudfront.ViewerProtocolPolicy.
                HTTPS_ONLY,
            ),
        )

        # We do not want someone to accidentally delete the
        # CloudFront distribution, since that would break
        # publicly-available distribution mechanisms. Set
        # the removal policy to RETAIN so that deleting
        # the `cloudformation` stack does not remove the
        # CloudFront resource.
        self.distribution.apply_removal_policy(core.RemovalPolicy.RETAIN)
Ejemplo n.º 15
0
    def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        #create the Cloudfront Function used to change the uri
        cf_function = cloudfront.Function(
            self,
            "Function",
            code=cloudfront.FunctionCode.from_file(
                file_path="cff/ab_testing.js"))

        #the S3 bucket where the html files will be hosted
        hosting_bucket = s3.Bucket(self, "MyHostingBucket")

        #copy the html files at deployment to the hosting bucket
        s3_deployment.BucketDeployment(
            self,
            "myDeployment",
            sources=[s3_deployment.Source.asset("website")],
            destination_bucket=hosting_bucket,
        )

        #create a cloudfront distribution and associate the cloudfront Function to the Distribution
        my_distribution = cloudfront.Distribution(
            self,
            "MyDistribution",
            default_behavior=cloudfront.BehaviorOptions(
                origin=origins.S3Origin(hosting_bucket),
                function_associations=[
                    cloudfront.FunctionAssociation(
                        function=cf_function,
                        event_type=cloudfront.FunctionEventType.VIEWER_REQUEST)
                ]))

        CfnOutput(self,
                  "DomainName",
                  value=my_distribution.domain_name,
                  export_name='DomainName',
                  description='CloudFront Domain Name')
def add_distribution(scope: core.Construct, id: str, alb_dns_name: str,
                     port: int, logbucket: s3.IBucket) -> cf.IDistribution:

    load_balancer_arn = core.Fn.get_att(alb_dns_name, "DNSName")
    security_group_id = core.Fn.get_att(alb_dns_name, "SecurityGroups")

    alb2 = alb.ApplicationLoadBalancer.from_application_load_balancer_attributes(
        scope,
        id,
        load_balancer_arn=load_balancer_arn.to_string(),
        security_group_id=security_group_id.to_string(),
        load_balancer_dns_name=alb_dns_name)
    _origin = origins.LoadBalancerV2Origin(
        alb2,
        http_port=port,
        protocol_policy=cf.OriginProtocolPolicy.HTTP_ONLY)
    dist = cf.Distribution(
        scope,
        "CF-" + id,
        default_behavior={
            "origin": _origin,
            "allowed_methods": cf.AllowedMethods.ALLOW_ALL,
            "cache_policy": cf.CachePolicy.CACHING_DISABLED,
            "origin_request_policy": cf.OriginRequestPolicy.ALL_VIEWER,
            "viewer_protocol_policy": cf.ViewerProtocolPolicy.REDIRECT_TO_HTTPS
        },
        minimum_protocol_version=cf.SecurityPolicyProtocol.TLS_V1_2_2019,
        enable_logging=True,
        log_bucket=logbucket)
    # Override Cfn_Nag rule for Cloudfront TLS-1.2 (https://github.com/stelligent/cfn_nag/issues/384)
    scan.suppress_cfnnag_rule(
        'W70',
        'the distribution uses CloudFront domain name and automatically sets the policy to TLSv1',
        dist.node.default_child)

    return dist.distribution_domain_name
Ejemplo n.º 17
0
    def __init__(self, scope: core.Construct, construct_id: str,
                 **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        # Domain name to redirect
        domain_name = core.CfnParameter(
            self,
            "domainName",
            type="String",
            description="Domain name to redirect",
        )

        # Here we use a specific certificate from parameter values
        cert_arn = core.CfnParameter(
            self,
            "certArn",
            type="String",
            description=
            "Certificate ARN of for the redirection (has to be in us-east-1",
        )

        image_tag = core.CfnParameter(
            self,
            "imageTag",
            type="String",
            description="Image tag to deploy as container",
        )

        processed_bucket_name = core.CfnParameter(
            self,
            "processedBucket",
            type="String",
            description="Name of the S3 bucket holding the processed data",
        )

        cookie_secret = core.CfnParameter(
            self,
            "cookieSecret",
            type="String",
            description=
            "The secret value to encrypt the login cookies by the dashboard.",
        )
        # End: Input variables

        # Create VPC and Fargate Cluster
        # NOTE: Limit AZs to avoid reaching resource quotas
        vpc = ec2.Vpc(self, "DashboardVPC", max_azs=2)

        cluster = ecs.Cluster(self,
                              "DashboardCluster",
                              vpc=vpc,
                              container_insights=True)

        repository = ecr.Repository(self,
                                    "DashboardRepository",
                                    repository_name="nccid-dashboard")
        secret = secretsmanager.Secret(self,
                                       "DashboardSecret",
                                       secret_name="nccid-dashboard-secrets")
        service_secret = ecs.Secret.from_secrets_manager(secret)

        fargate_service = ecs_patterns.NetworkLoadBalancedFargateService(
            self,
            "DashboardService",
            cluster=cluster,
            task_image_options={
                "image":
                ecs.ContainerImage.from_ecr_repository(
                    repository=repository, tag=image_tag.value_as_string),
                "secrets": [service_secret],
                "environment": {
                    "AWS_PROCESSED_BUCKET":
                    processed_bucket_name.value_as_string,
                    "COOKIE_SECRET_KEY": cookie_secret.value_as_string,
                    "DASHBOARD_DOMAIN": domain_name.value_as_string,
                },
            },
            platform_version=ecs.FargatePlatformVersion.VERSION1_4,
            # See values for these entries at https://docs.aws.amazon.com/cdk/api/latest/python/aws_cdk.aws_ecs_patterns/NetworkLoadBalancedFargateService.html#networkloadbalancedfargateservice
            cpu=256,  # .25 vCPU
            memory_limit_mib=512,  # 0.5 GB
        )

        processed_bucket = s3.Bucket.from_bucket_name(
            self,
            id="ProcessedBucket",
            bucket_name=processed_bucket_name.value_as_string,
        )
        processed_bucket.grant_read(fargate_service.task_definition.task_role)

        fargate_service.service.connections.security_groups[
            0].add_ingress_rule(
                peer=ec2.Peer.ipv4(vpc.vpc_cidr_block),
                connection=ec2.Port.tcp(80),
                description="Allow HTTP inbound from VPC",
            )

        cert = _acm.Certificate.from_certificate_arn(self, "cert",
                                                     cert_arn.value_as_string)

        origin = _origins.HttpOrigin(
            domain_name=fargate_service.load_balancer.load_balancer_dns_name,
            protocol_policy=_cloudfront.OriginProtocolPolicy.HTTP_ONLY,
        )
        behaviour = _cloudfront.BehaviorOptions(
            origin=origin,
            allowed_methods=_cloudfront.AllowedMethods.ALLOW_ALL,
            cache_policy=_cloudfront.CachePolicy.CACHING_DISABLED,
            origin_request_policy=_cloudfront.OriginRequestPolicy.ALL_VIEWER,
            viewer_protocol_policy=_cloudfront.ViewerProtocolPolicy.
            REDIRECT_TO_HTTPS,
        )

        distribution = _cloudfront.Distribution(
            self,
            "nccid-dasboard-dist",
            default_behavior=behaviour,
            certificate=cert,
            domain_names=[domain_name.value_as_string],
        )
        # Explicit dependency setup
        distribution.node.add_dependency(fargate_service.load_balancer)

        core.CfnOutput(
            self,
            "nccidCloudfrontDistribution",
            value=distribution.distribution_domain_name,
            description="Cloudfront domain to set the CNAME for.",
        )
Ejemplo n.º 18
0
    def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)
        self.current_dir = os.path.dirname(__file__)

        self.website_bucket = s3.Bucket(
            self,
            "qs-embed-bucket",
            bucket_name=f'quicksight-embed-{core.Aws.ACCOUNT_ID}',
            block_public_access=s3.BlockPublicAccess.BLOCK_ALL)

        self.quicksight_embed_lambda_role = iam.Role(
            self,
            'quicksight-embed-lambda-role',
            description='Role for the Quicksight dashboard embed Lambdas',
            role_name='quicksight-embed-lambda-role',
            max_session_duration=core.Duration.seconds(3600),
            assumed_by=iam.ServicePrincipal('lambda.amazonaws.com'),
            inline_policies={
                'AllowAccess':
                iam.PolicyDocument(statements=[
                    iam.PolicyStatement(
                        effect=iam.Effect.ALLOW,
                        actions=[
                            'logs:CreateLogGroup', 'logs:CreateLogStream',
                            'logs:PutLogEvents'
                        ],
                        resources=[
                            f'arn:aws:logs:{core.Aws.REGION}:{core.Aws.ACCOUNT_ID}:*'
                        ]),
                    iam.PolicyStatement(
                        effect=iam.Effect.ALLOW,
                        actions=["secrets:GetSecretValue"],
                        resources=[
                            f"arn:aws:secretsmanager:{core.Aws.REGION}:{core.Aws.ACCOUNT_ID}:secret:*"
                        ]),
                    iam.PolicyStatement(effect=iam.Effect.ALLOW,
                                        actions=[
                                            "quicksight:GetDashboardEmbedUrl",
                                            "quicksight:GetAuthCode"
                                        ],
                                        resources=["*"])
                ])
            })

        self.quicksight_migration_lambda = _lambda.Function(
            self,
            'quicksight-migration-lambda',
            handler='quicksight_embed.lambda_handler',
            runtime=_lambda.Runtime.PYTHON_3_8,
            code=_lambda.Code.from_asset(
                os.path.join(self.current_dir, '../lambda/quicksight_embed/')),
            function_name='quicksight_embed_lambda',
            role=self.quicksight_embed_lambda_role,
            timeout=core.Duration.minutes(3),
            memory_size=512,
            environment={
                'DASHBOARD_ID':
                'CHANGEME_DASHBOARD_ID',
                'QUICKSIGHT_USER_ARN':
                f'arn:aws:quicksight:us-east-1:{core.Aws.ACCOUNT_ID}:user/default/quicksight-migration-user'
            })

        self.apigw_lambda = ApiGatewayToLambda(
            self,
            "ApiGatewayToLambdaQSEmbed",
            existing_lambda_obj=self.quicksight_migration_lambda,
            api_gateway_props=apigw.LambdaRestApiProps(
                rest_api_name="quicksight-embed",
                handler=self.quicksight_migration_lambda,
                deploy=True,
                proxy=False,
                default_method_options=apigw.MethodOptions(
                    authorization_type=apigw.AuthorizationType.NONE),
                policy=iam.PolicyDocument(statements=[
                    iam.PolicyStatement(effect=iam.Effect.ALLOW,
                                        actions=['execute-api:Invoke'],
                                        resources=["execute-api:/prod/*"],
                                        principals=[iam.ArnPrincipal("*")])
                ])))

        self.embedurl = self.apigw_lambda.api_gateway.root.add_resource(
            "embedurl")
        self.embedurl.add_method(
            "GET",
            method_responses=[{
                'statusCode': '200',
                'responseParameters': {
                    'method.response.header.Access-Control-Allow-Headers':
                    True,
                    'method.response.header.Access-Control-Allow-Methods':
                    True,
                    'method.response.header.Access-Control-Allow-Origin': True
                }
            }],
            integration=apigw.LambdaIntegration(
                self.quicksight_migration_lambda,
                proxy=False,
                integration_responses=[{
                    'statusCode': '200',
                    'responseTemplates': {
                        "application/json": ""
                    },
                    'responseParameters': {
                        'method.response.header.Access-Control-Allow-Headers':
                        "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'",
                        'method.response.header.Access-Control-Allow-Origin':
                        "'*'",
                        'method.response.header.Access-Control-Allow-Methods':
                        "'GET'"
                    }
                }]))

        self.embedurl.add_method(
            'OPTIONS',
            apigw.MockIntegration(integration_responses=[{
                'statusCode': '200',
                'responseParameters': {
                    'method.response.header.Access-Control-Allow-Headers':
                    "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'",
                    'method.response.header.Access-Control-Allow-Origin':
                    "'*'",
                    'method.response.header.Access-Control-Allow-Methods':
                    "'GET,OPTIONS'"
                }
            }],
                                  passthrough_behavior=apigw.
                                  PassthroughBehavior.WHEN_NO_MATCH,
                                  request_templates={
                                      "application/json":
                                      "{\"statusCode\":200}"
                                  }),
            method_responses=[{
                'statusCode': '200',
                'responseParameters': {
                    'method.response.header.Access-Control-Allow-Headers':
                    True,
                    'method.response.header.Access-Control-Allow-Methods':
                    True,
                    'method.response.header.Access-Control-Allow-Origin': True
                }
            }])

        # Cloudfront Distribution for authentication
        self.embed_auth_lambda_role = iam.Role(
            self,
            'embed-auth-lambda-role',
            description=
            'Role for the Quicksight dashboard embed authentication Lambda',
            role_name='embed-auth-lambda-role',
            max_session_duration=core.Duration.seconds(3600),
            assumed_by=iam.ServicePrincipal('lambda.amazonaws.com'),
            inline_policies={
                'AllowAccess':
                iam.PolicyDocument(statements=[
                    iam.PolicyStatement(
                        effect=iam.Effect.ALLOW,
                        actions=[
                            'logs:CreateLogGroup', 'logs:CreateLogStream',
                            'logs:PutLogEvents'
                        ],
                        resources=[
                            f'arn:aws:logs:{core.Aws.REGION}:{core.Aws.ACCOUNT_ID}:*'
                        ])
                ])
            })

        self.embed_auth_lambda = _lambda.Function(
            self,
            'embed-auth-lambda',
            handler='index.handler',
            description=
            "A Lambda@Edge function for QuickSight embed authentication via CloudFront Distribution",
            runtime=_lambda.Runtime.NODEJS_14_X,
            code=_lambda.Code.from_asset(
                os.path.join(self.current_dir, '../lambda/embed_auth/')),
            function_name='embed_auth_lambda',
            role=self.embed_auth_lambda_role,
            timeout=core.Duration.seconds(5),
            memory_size=128)

        self.embed_auth_dist = cloudfront.Distribution(
            self,
            "embed-auth-dist",
            enabled=True,
            default_root_object="index.html",
            default_behavior=cloudfront.BehaviorOptions(
                origin=origins.S3Origin(self.website_bucket),
                allowed_methods=cloudfront.AllowedMethods.ALLOW_GET_HEAD,
                edge_lambdas=[{
                    "functionVersion": self.embed_auth_lambda.current_version,
                    "eventType": cloudfront.LambdaEdgeEventType.VIEWER_REQUEST,
                    "includeBody": True
                }]))

        core.CfnOutput(self,
                       "EmbedAPIGatewayURL",
                       value=self.apigw_lambda.api_gateway.url + "embedurl?",
                       description="Embed API GW URL")

        core.CfnOutput(self,
                       "EmbedCloudFrontURL",
                       value="https://" +
                       self.embed_auth_dist.distribution_domain_name,
                       description="CloudFront Distribution URL")
Ejemplo n.º 19
0
    def __init__(self, scope: core.Construct, construct_id: str,
                 ss_context: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        # Access logging bucket for the S3 and Cloudfront

        ss = dict(self.node.try_get_context(ss_context))

        allowed_methods = AllowedMethods.ALLOW_GET_HEAD if ss[
            "cfront_allowed_methods"] == "ALLOW_GET_HEAD" else AllowedMethods.ALLOW_GET_HEAD_OPTIONS if ss[
                "cfront_allowed_methods"] == "ALLOW_GET_HEAD_OPTIONS" else AllowedMethods.ALLOW_ALL

        viewer_policy = ViewerProtocolPolicy.REDIRECT_TO_HTTPS if ss[
            "cfront_viewer_policy"] == "REDIRECT_TO_HTTPS" else ViewerProtocolPolicy.HTTPS_ONLY if ss[
                "cfront_viewer_policy"] == "HTTPS_ONLY" else ViewerProtocolPolicy.ALLOW_ALL

        price_class = PriceClass.PRICE_CLASS_ALL if ss[
            "cfront_price_class"] == "PRICE_CLASS_ALL" else PriceClass.PRICE_CLASS_200 if ss[
                "cfront_price_class"] == "PRICE_CLASS_200" else PriceClass.PRICE_CLASS_100

        # Creating the access logs bucket

        access_log_bucket = _s3.Bucket(
            self,
            ss["access_logs_bucket_name"],
            bucket_name=ss["access_logs_bucket_name"],
            encryption=_s3.BucketEncryption.KMS_MANAGED,
            removal_policy=core.RemovalPolicy.DESTROY,
            auto_delete_objects=True,
        )

        # S3 bucket for the static site

        source_bucket = _s3.Bucket(
            self,
            ss["static_site_bucket_name"],
            bucket_name=ss["static_site_bucket_name"],
            encryption=_s3.BucketEncryption.KMS_MANAGED,
            removal_policy=core.RemovalPolicy.DESTROY,
            auto_delete_objects=True,
            versioned=True,
            website_index_document=ss["website_index_document"],
            website_error_document=ss["website_index_document"])

        bucket_origins = _cfront_origins.S3Origin(source_bucket)

        # Cloudfront distribution with S3 as origin and logging enabled

        cfront_oai = _cfront.CfnCloudFrontOriginAccessIdentity(
            self,
            "accessOriginOAI",
            cloud_front_origin_access_identity_config={
                "comment": ss["cfront_origins_comment"]
            })

        cfront_dist = _cfront.Distribution(
            self,
            ss["cfront_distribution_name"],
            default_behavior={
                "origin": bucket_origins,
                "allowed_methods": allowed_methods,
                "viewer_protocol_policy": viewer_policy
            },
            enable_ipv6=True,
            minimum_protocol_version=SecurityPolicyProtocol.TLS_V1_2_2019,
            price_class=price_class,
            default_root_object=ss["cfront_root_object"],
            comment=ss["cfront_dist_comment"],
            log_bucket=access_log_bucket,
            log_includes_cookies=False,
            log_file_prefix=ss["cfront_log_file_prefix"],
            # web_acl_id=,
            # certificate=,
            geo_restriction=GeoRestriction.whitelist(ss["geo_whitelist"]),
        )

        # Bucket policy to restrict access to bucket - Use only cloudfront's Origin Access identity
        policy_statement = _iam.PolicyStatement()
        policy_statement.add_actions('s3:GetBucket*')
        policy_statement.add_actions('s3:GetObject*')
        policy_statement.add_actions('s3:List*')
        policy_statement.add_resources(source_bucket.bucket_arn)
        policy_statement.add_resources(f"{source_bucket.bucket_arn}/*")
        policy_statement.add_canonical_user_principal(
            cfront_oai.attr_s3_canonical_user_id)
        source_bucket.add_to_resource_policy(policy_statement)

        # Outputs

        core.CfnOutput(self,
                       "CloudfrontDistribution",
                       value=(cfront_dist.distribution_domain_name))
        core.CfnOutput(self, "BucketArn", value=(source_bucket.bucket_arn))
        core.CfnOutput(self,
                       "LoggingBucketArn",
                       value=(access_log_bucket.bucket_arn))

        self.bucket = source_bucket
        self.access_logs_bucket = access_log_bucket
        self.cfront_dist = cfront_dist
Ejemplo n.º 20
0
    def __init__(self, app: core.App, id: str) -> None:
        super().__init__(app, id)

        with open("config.json") as f:
            self.config = json.load(f)
        assert (
            "SECRET_KEY"
            in self.config), "Need random SECRET_KEY specified in config.json"
        assert (
            "CERTIFICATE_ARN"
            in self.config), "Need CERTIFICATE_ARN specified in config.json"

        self.lambda_dir = "assets/lambda"
        os.makedirs(os.path.join(self.lambda_dir, "templates", "generated"),
                    exist_ok=True)

        r = requests.get(
            "https://api.github.com/repos/sumpfork/dominiontabs/releases")
        changelog = r.json()
        changelog = [{
            "url":
            ch["html_url"],
            "date":
            dt.datetime.strptime(ch["published_at"][:10], "%Y-%m-%d").date(),
            "name":
            ch["name"],
            "tag":
            ch["tag_name"],
            "description":
            ch["body"],
        } for ch in changelog]

        env = Environment(loader=FileSystemLoader("templates"),
                          autoescape=select_autoescape(["html"]))
        t = env.get_template("changelog.html.j2")
        generated_template_path = os.path.join(self.lambda_dir, "templates",
                                               "generated")
        shutil.rmtree(generated_template_path)
        os.mkdir(generated_template_path)

        with open(
                os.path.join(generated_template_path, "changelog.html"),
                "w",
        ) as f:
            f.write(t.render(changelog=changelog))

        static_website_bucket = s3.Bucket(
            self,
            "Dominion Divider Generator Site",
        )

        cf_static_dist = cloudfront.Distribution(
            self,
            "StaticCloudfrontDist",
            default_behavior=cloudfront.BehaviorOptions(
                origin=cloudfront_origins.S3Origin(static_website_bucket)),
        )

        s3_deployment.BucketDeployment(
            self,
            "Static Files Deployment",
            sources=[s3_deployment.Source.asset("./static")],
            destination_bucket=static_website_bucket,
            destination_key_prefix="static",
        )

        flask_app = lambda_python.PythonFunction(
            self,
            "DominionDividersFlaskApp",
            entry=self.lambda_dir,
            index="lambda-handlers.py",
            handler="apig_wsgi_handler",
            environment={
                "STATIC_WEB_URL": f"https://{cf_static_dist.domain_name}",
                "FLASK_SECRET_KEY": self.config["SECRET_KEY"],
                "GA_CONFIG": self.config.get("GA_CONFIG", ""),
            },
            timeout=core.Duration.seconds(60),
            memory_size=512,
            runtime=lambda_.Runtime.PYTHON_3_8,
        )
        api = apig.LambdaRestApi(
            self,
            "bgtools-api",
            handler=flask_app,
            binary_media_types=["*/*"],
            minimum_compression_size=10e4,
            deploy_options={
                "method_options": {
                    "/*/*":
                    apig.MethodDeploymentOptions(throttling_rate_limit=10,
                                                 throttling_burst_limit=20)
                }
            },
        )
        cloudfront.Distribution(
            self,
            "BGToolsCloudfrontDist",
            default_behavior=cloudfront.BehaviorOptions(
                origin=cloudfront_origins.HttpOrigin(
                    core.Fn.select(2, core.Fn.split("/", api.url)),
                    origin_path=core.Fn.join(
                        "",
                        ["/",
                         core.Fn.select(3, core.Fn.split("/", api.url))]),
                ),
                origin_request_policy=cloudfront.OriginRequestPolicy(
                    self,
                    "OriginRequestPolicy",
                    cookie_behavior=cloudfront.OriginRequestCookieBehavior.all(
                    ),
                ),
                allowed_methods=cloudfront.AllowedMethods.ALLOW_ALL,
            ),
            domain_names=["domdiv.bgtools.net"],
            certificate=acm.Certificate.from_certificate_arn(
                self,
                "cert",
                self.config["CERTIFICATE_ARN"],
            ),
        )

        dashboard = aws_cloudwatch.Dashboard(
            self,
            f"bgtools-dashboard",
            dashboard_name=f"bgtools-prod",
            start="-P1D",
            period_override=aws_cloudwatch.PeriodOverride.INHERIT,
        )
        dashboard.add_widgets(
            aws_cloudwatch.GraphWidget(
                title="API Gateway Counts",
                width=6,
                height=6,
                left=[
                    aws_cloudwatch.Metric(
                        namespace="AWS/ApiGateway",
                        metric_name="5XXError",
                        dimensions={
                            "ApiName": "bgtools-api",
                            "Stage": api.deployment_stage.stage_name,
                        },
                        period=core.Duration.minutes(amount=30),
                        statistic="Sum",
                        color="#d62728",
                    ),
                    aws_cloudwatch.Metric(
                        namespace="AWS/ApiGateway",
                        metric_name="4XXError",
                        dimensions={
                            "ApiName": "bgtools-api",
                            "Stage": api.deployment_stage.stage_name,
                        },
                        period=core.Duration.minutes(amount=30),
                        statistic="Sum",
                        color="#8c564b",
                    ),
                    aws_cloudwatch.Metric(
                        namespace="AWS/ApiGateway",
                        metric_name="Count",
                        dimensions={
                            "ApiName": "bgtools-api",
                            "Stage": api.deployment_stage.stage_name,
                        },
                        period=core.Duration.minutes(amount=30),
                        statistic="Sum",
                        color="#2ca02c",
                    ),
                ],
            ),
            aws_cloudwatch.GraphWidget(
                title="API Gateway Latencies",
                width=6,
                height=6,
                left=[
                    aws_cloudwatch.Metric(
                        namespace="AWS/ApiGateway",
                        metric_name="Latency",
                        dimensions={
                            "ApiName": "bgtools-api",
                            "Stage": api.deployment_stage.stage_name,
                        },
                        period=core.Duration.minutes(amount=30),
                        statistic="Average",
                    ),
                    aws_cloudwatch.Metric(
                        namespace="AWS/ApiGateway",
                        metric_name="IntegrationLatency",
                        dimensions={
                            "ApiName": "bgtools-api",
                            "Stage": api.deployment_stage.stage_name,
                        },
                        period=core.Duration.minutes(amount=30),
                        statistic="Average",
                    ),
                ],
            ),
        )
Ejemplo n.º 21
0
    def __init__(self, scope: core.Construct, construct_id: str,
                 **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        # Input variables

        # Domain name to redirect
        domain_name = core.CfnParameter(
            self,
            "domainName",
            type="String",
            description="Domain name to redirect",
        )

        # Here we use a specific certificate from parameter values
        cert_arn = core.CfnParameter(
            self,
            "certArn",
            type="String",
            description=
            "Certificate ARN of for the redirection (has to be in us-east-1",
        )
        # End: Input variables

        # Infra setup

        redirect_fn = _lambda.Function(
            self,
            "NCCIDRedirectLambda",
            handler="lambda-handler.handler",
            runtime=_lambda.Runtime.PYTHON_3_8,
            code=_lambda.Code.asset("lambda"),
        )

        redirect_integration = _apigw2int.LambdaProxyIntegration(
            handler=redirect_fn)

        cert = _acm.Certificate.from_certificate_arn(self, "cert",
                                                     cert_arn.value_as_string)

        http_api = _apigw2.HttpApi(
            self,
            "nccid-redirect",
            api_name="nccid-redirect",
            description="A redirection gateway.",
        )

        http_api.add_routes(path="/",
                            methods=[_apigw2.HttpMethod.GET],
                            integration=redirect_integration)

        # Change https address into just domain name (while keeping the Cloudformation variables in)
        origin_target = http_api.url.replace("https://", "",
                                             1).replace("/", "")
        origin = _origins.HttpOrigin(domain_name=origin_target)
        behaviour = _cloudfront.BehaviorOptions(origin=origin)

        distribution = _cloudfront.Distribution(
            self,
            "nccid-redirect-dist",
            default_behavior=behaviour,
            certificate=cert,
            domain_names=[domain_name.value_as_string],
        )
        # Explicit dependency is required between the API gateway and Cloudfront distribution
        distribution.node.add_dependency(http_api)

        # Outputs
        distribution_domain = core.CfnOutput(  # noqa:  F841
            self,
            "nccidRedirectDomain",
            value=distribution.distribution_domain_name,
            description=
            "The Cloudfront domain to add to the CNAME records for the redirected domain",
        )
Ejemplo n.º 22
0
def create_static_site(scope: InfraStack, hosted_zone: route53.HostedZone):
    bucket = s3.Bucket(
        scope,
        id=scope.context.construct_id("s3"),
        bucket_name=f'{scope.context.construct_id("s3")}-bucket',
        versioned=True,
        block_public_access=s3.BlockPublicAccess(
            restrict_public_buckets=True,
            block_public_policy=True,
            block_public_acls=True,
        ),
        removal_policy=RemovalPolicy.RETAIN,
        auto_delete_objects=False,
        lifecycle_rules=[
            s3.LifecycleRule(noncurrent_version_expiration=Duration.days(7))
        ],
    )

    prod_domain_name = "gingerbeans.tech"
    lower_domain_name = f"{scope.context.env_name}.gingerbeans.tech"
    domain_name = (prod_domain_name if scope.context.env_name == PRODUCTION
                   else lower_domain_name)

    my_certificate = acm.DnsValidatedCertificate(
        scope,
        scope.context.construct_id("certificate"),
        domain_name=domain_name,
        hosted_zone=hosted_zone,
        region="us-east-1",
    )

    origin_access_identity = cloudfront.OriginAccessIdentity(
        scope, scope.context.construct_id("cfOriginAccessIdentity"))
    cf_s3_access = iam.PolicyStatement()
    cf_s3_access.add_actions("s3:GetBucket*")
    cf_s3_access.add_actions("s3:GetObject*")
    cf_s3_access.add_actions("s3:List*")
    cf_s3_access.add_resources(bucket.bucket_arn)
    cf_s3_access.add_resources(f"{bucket.bucket_arn}/*")
    cf_s3_access.add_canonical_user_principal(
        origin_access_identity.
        cloud_front_origin_access_identity_s3_canonical_user_id)
    bucket.add_to_resource_policy(cf_s3_access)

    distro = cloudfront.Distribution(
        scope,
        scope.context.construct_id("dist"),
        default_behavior=cloudfront.BehaviorOptions(origin=origins.S3Origin(
            bucket=bucket, origin_access_identity=origin_access_identity)),
        default_root_object="index.html",
        domain_names=[domain_name],
        certificate=my_certificate,
    )

    route53.AaaaRecord(
        scope,
        scope.context.construct_id("AAAA"),
        record_name=domain_name,
        target=route53.RecordTarget.from_alias(
            targets.CloudFrontTarget(distro)),
        zone=hosted_zone,
    )

    route53.ARecord(
        scope,
        scope.context.construct_id("A"),
        record_name=domain_name,
        target=route53.RecordTarget.from_alias(
            targets.CloudFrontTarget(distro)),
        zone=hosted_zone,
    )

    s3_deployment.BucketDeployment(
        scope,
        scope.context.construct_id("s3_deployment"),
        sources=[s3_deployment.Source.asset("../gb-ui/build")],
        destination_key_prefix="/",
        destination_bucket=bucket,
        distribution=distro,
        distribution_paths=["/*"],
    )
Ejemplo n.º 23
0
    def __init__(self, scope: core.Construct, construct_id: str, origin, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        # The code that defines your stack goes here

        # web_acl = waf.CfnWebACL(self, "WAF ACL",
        #                         default_action={"allow": {}},
        #                         scope="GLOBAL",
        #                         visibility_config={
        #                             "sampledRequestsEnabled": True,
        #                             "cloudWatchMetricsEnabled": True,
        #                             "metricName": "web-acl",
        #                         },
        #                         rules=[
        #                             {
        #                                 "name": "rate_limit_500",
        #                                 "priority": 0,
        #                                 "action": {
        #                                     "block": {}
        #                                 },
        #                                 "visibilityConfig": {
        #                                     "sampledRequestsEnabled": True,
        #                                     "cloudWatchMetricsEnabled": True,
        #                                     "metricName": "rate_limit_500"
        #                                 },
        #                                 "statement": {
        #                                     "rateBasedStatement": {
        #                                         "limit": 500,
        #                                         "aggregateKeyType": "IP"
        #                                     }
        #                                 }
        #                             },
        #                             {
        #                                 "priority": 1,
        #                                 "overrideAction": {"none": {}},
        #                                 "visibilityConfig": {
        #                                     "sampledRequestsEnabled": True,
        #                                     "cloudWatchMetricsEnabled": True,
        #                                     "metricName": "AWS-AWSManagedRulesAmazonIpReputationList",
        #                                 },
        #                                 "name": "AWS-AWSManagedRulesAmazonIpReputationList",
        #                                 "statement": {
        #                                     "managedRuleGroupStatement": {
        #                                         "vendorName": "AWS",
        #                                         "name": "AWSManagedRulesAmazonIpReputationList",
        #                                     },
        #                                 },
        #                             },
        #                             {
        #                                 "priority": 2,
        #                                 "overrideAction": {"none": {}},
        #                                 "visibilityConfig": {
        #                                     "sampledRequestsEnabled": True,
        #                                     "cloudWatchMetricsEnabled": True,
        #                                     "metricName": "AWS-AWSManagedRulesCommonRuleSet",
        #                                 },
        #                                 "name": "AWS-AWSManagedRulesCommonRuleSet",
        #                                 "statement": {
        #                                     "managedRuleGroupStatement": {
        #                                         "vendorName": "AWS",
        #                                         "name": "AWSManagedRulesCommonRuleSet",
        #                                     },
        #                                 },
        #                             },
        #                             {
        #                                 "priority": 3,
        #                                 "overrideAction": {"none": {}},
        #                                 "visibilityConfig": {
        #                                     "sampledRequestsEnabled": True,
        #                                     "cloudWatchMetricsEnabled": True,
        #                                     "metricName": "AWS-AWSManagedRulesKnownBadInputsRuleSet",
        #                                 },
        #                                 "name": "AWS-AWSManagedRulesKnownBadInputsRuleSet",
        #                                 "statement": {
        #                                     "managedRuleGroupStatement": {
        #                                         "vendorName": "AWS",
        #                                         "name": "AWSManagedRulesKnownBadInputsRuleSet",
        #                                     },
        #                                 },
        #                             },
        #                             {
        #                                 "priority": 4,
        #                                 "overrideAction": {"none": {}},
        #                                 "visibilityConfig": {
        #                                     "sampledRequestsEnabled": True,
        #                                     "cloudWatchMetricsEnabled": True,
        #                                     "metricName": "AWS-AWSManagedRulesSQLiRuleSet",
        #                                 },
        #                                 "name": "AWS-AWSManagedRulesSQLiRuleSet",
        #                                 "statement": {
        #                                     "managedRuleGroupStatement": {
        #                                         "vendorName": "AWS",
        #                                         "name": "AWSManagedRulesSQLiRuleSet",
        #                                     },
        #                                 },
        #                             }
        #                         ]
        #                         )

        certificate = acm.Certificate.from_certificate_arn(
            self, "Certificate", acm_arn)

        distribution = cloudfront.Distribution(self, "myDist",
                                               default_behavior={
                                                   "origin": origins.LoadBalancerV2Origin(origin, protocol_policy=cloudfront.OriginProtocolPolicy.MATCH_VIEWER),
                                                   "viewer_protocol_policy": cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
                                                   "cache_policy": cloudfront.CachePolicy(self, "myCachePolicy",
                                                                                          cache_policy_name="MyPolicy",
                                                                                          comment="A default policy",
                                                                                          default_ttl=core.Duration.minutes(
                                                                                              0),
                                                                                          min_ttl=core.Duration.minutes(
                                                                                              0),
                                                                                          max_ttl=core.Duration.minutes(
                                                                                              5),
                                                                                          )
                                               },
                                               domain_names=[f'www.{domain}'],
                                               certificate=certificate,
                                               # web_acl_id=web_acl.attr_arn
                                               )

        hosted_zone = route53.HostedZone.from_hosted_zone_attributes(self, "MyZone",
                                                                     zone_name=domain,
                                                                     hosted_zone_id=hosted_zone_id
                                                                     )

        route53.ARecord(self, "Alias",
                        zone=hosted_zone,
                        target=route53.RecordTarget.from_alias(
                            targets.CloudFrontTarget(distribution)),
                        record_name=f'www.{domain}',
                        ttl=core.Duration.minutes(5)
                        )