示例#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, '_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)
示例#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 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
示例#4
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 __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)
示例#6
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')
示例#7
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",
     )
示例#8
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)
         ])
示例#10
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)
示例#11
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')
示例#12
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",
                    ),
                ],
            ),
        )
示例#13
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")
示例#14
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=["/*"],
    )
示例#15
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