コード例 #1
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,
            '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)
コード例 #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,
                )
            })
コード例 #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
コード例 #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
コード例 #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
コード例 #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))
コード例 #7
0
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
コード例 #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)
コード例 #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')
コード例 #10
0
    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)
コード例 #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",
     )
コード例 #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')
コード例 #13
0
 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)
         ])
コード例 #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)
コード例 #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
コード例 #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.",
        )
コード例 #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")
コード例 #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
コード例 #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",
                    ),
                ],
            ),
        )
コード例 #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",
        )
コード例 #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=["/*"],
    )
コード例 #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)
                        )