コード例 #1
0
    def create_records(self):
        """
        Setup route53 entries
        At a minimum:
          A Record: subdomain.example.com
        Optional:
          A Record: example.com
          AAAA Record: example.com
          AAAA Record: subdomain.example.com
        """
        self.cloudfront_site_target = route53.RecordTarget.from_alias(
            route53_targets.CloudFrontTarget(
                self.site_distribution
            )
        )
        if self.config.get("redirect_apex", True):
            apex_target = route53.RecordTarget.from_alias(
                route53_targets.CloudFrontTarget(
                    self.redirect_distribution
                )
            )
        else:
            apex_target = self.cloudfront_site_target

        self.create_site_records()
        self.create_apex_records(apex_target)
コード例 #2
0
 def __create_route53_record(self, hosted_zone):
     route53.ARecord(
         self,
         "site-alias-record",
         record_name=self._site_domain_name,
         zone=hosted_zone,
         target=route53.RecordTarget.from_alias(
             targets.CloudFrontTarget(self.distribution)),
     )
コード例 #3
0
def generate_record_in_hosted_zone(scope, hosted_zone: route53.HostedZone,
                                   cloudfront_distribution):
    a_record = route53.ARecord(
        scope,
        "CloudfrontTier1Route53ARecord",
        zone=hosted_zone,
        target=route53.RecordTarget.from_alias(
            targets.CloudFrontTarget(cloudfront_distribution)),
        record_name="jvsantos-tier1.apperdevops.com")
    return a_record
コード例 #4
0
    def __init__(self, scope: core.Construct, id: str, domain: DomainInfo,
                 **kwargs) -> None:
        super().__init__(scope, id, **kwargs)
        if domain.stage == 'prod':
            self.final_domain = domain.domain_name
        else:
            self.final_domain = f'{domain.stage}.{domain.domain_name}'
        self.domain = domain

        # Create the static site website bucket
        bucket = s3.Bucket(self,
                           "sitebucket",
                           bucket_name=self.final_domain,
                           public_read_access=True,
                           website_index_document="index.html")
        core.CfnOutput(self, 'site_bucket_name', value=bucket.bucket_name)
        core.CfnOutput(self,
                       'site_bucket_website',
                       value=bucket.bucket_website_url)

        #create Cloudfront distribution return dist ID
        alias_configuration = cf.AliasConfiguration(
            acm_cert_ref=self.domain.cert_arn,
            names=[self.final_domain],
        )
        source_configuration = cf.SourceConfiguration(
            s3_origin_source=cf.S3OriginConfig(s3_bucket_source=bucket, ),
            behaviors=[cf.Behavior(is_default_behavior=True)])
        dist = cf.CloudFrontWebDistribution(
            self,
            'staticsitecf',
            alias_configuration=alias_configuration,
            origin_configs=[source_configuration],
        )
        core.CfnOutput(self,
                       'static_site_cf_dist_id',
                       value=dist.distribution_id)
        core.CfnOutput(self, 'static_site_cf_domain', value=dist.domain_name)

        #route53 logic
        if self.domain.stage == 'prod':
            zone = route53.HostedZone.from_hosted_zone_attributes(
                self,
                id="HostedZoneID",
                hosted_zone_id=self.domain.hosted_zone_id,
                zone_name=self.domain.domain_name)
            route53.ARecord(self,
                            'SiteAliasRecord',
                            record_name=self.final_domain,
                            target=route53.AddressRecordTarget.from_alias(
                                targets.CloudFrontTarget(dist)),
                            zone=zone)
コード例 #5
0
    def __init__(self, parent: core.Construct, name: str,
                 props: StaticSiteProps) -> None:
        super().__init__(parent, name)

        site_domain = props.site_sub_domain + '.' + props.domain_name

        # Content bucket
        site_bucket = s3.Bucket(self,
                                "SiteBucket",
                                bucket_name=site_domain,
                                website_index_document="index.html",
                                website_error_document="error.html",
                                public_read_access=True,
                                removal_policy=core.RemovalPolicy.DESTROY)

        core.CfnOutput(self, 'Bucket', value=site_bucket.bucket_name)

        #cloudfront distribution that provies HTTPS
        distribution = cfront.CloudFrontWebDistribution(
            self,
            'SiteDistribution',
            origin_configs=[
                cfront.SourceConfiguration(
                    behaviors=[cfront.Behavior(is_default_behavior=True)],
                    s3_origin_source=cfront.S3OriginConfig(
                        s3_bucket_source=site_bucket))
            ],
            alias_configuration=cfront.AliasConfiguration(
                acm_cert_ref=props.certificate_arn,
                names=[site_domain],
                ssl_method=cfront.SSLMethod.SNI,
                security_policy=cfront.SecurityPolicyProtocol.TLS_V1_1_2016))

        core.CfnOutput(self,
                       'DistributionID',
                       value=distribution.distribution_id)

        # Route 53 alias record for the CloudFront distribution
        zone = route53.HostedZone.from_lookup(self,
                                              'MyHostedZone',
                                              domain_name=props.domain_name)

        # Add a A record to the hosted zone
        route53.ARecord(
            self,
            'SiteAliasRecord',
            zone=zone,
            record_name=site_domain,
            target=route53.AddressRecordTarget.from_alias(
                aws_route53_targets.CloudFrontTarget(distribution)))
コード例 #6
0
    def __init__(self, app: core.App, id: str, **kwargs) -> None:
        super().__init__(app, id)
        #create an S3 bucket
        domainName = 'accelerate.dev'
        myBucket = s3.Bucket(self,
                             'accelerate.dev-s3bucket',
                             bucket_name='accelerate-website',
                             public_read_access=True,
                             website_index_document='index.html',
                             website_error_document='404.html',
                             removal_policy=core.RemovalPolicy.DESTROY)
        myBucket.grant_public_access
        myBucket.add_to_resource_policy(  #Grant read access to everyone in your account
            iam.PolicyStatement(
                actions=['s3:GetObject'],
                resources=[myBucket.arn_for_objects('*')],
                principals=[
                    iam.AccountPrincipal(account_id=core.Aws.ACCOUNT_ID)
                ]))
        myUser = iam.User(self, 'deploy_' +
                          domainName)  #Grant write access to a specific user
        myBucket.grant_write(myUser)
        hostedZone = route53.HostedZone.from_hosted_zone_attributes(
            self,
            "HostedZone_" + domainName,
            hosted_zone_id='Z00154093I7THXRTRF8QB',
            zone_name=domainName)
        cert = certmgr.DnsValidatedCertificate(self,
                                               "cert_" + domainName,
                                               domain_name=domainName,
                                               hosted_zone=hostedZone)
        distribution = cloudfront.CloudFrontWebDistribution(
            self,
            "accelerate.dev-distribution",
            price_class=cloudfront.PriceClass.PRICE_CLASS_100,
            origin_configs=[
                cloudfront.SourceConfiguration(
                    s3_origin_source=cloudfront.S3OriginConfig(
                        s3_bucket_source=myBucket),
                    behaviors=[cloudfront.Behavior(is_default_behavior=True)])
            ],
            viewer_certificate=cloudfront.ViewerCertificate.
            from_acm_certificate(cert, aliases=['accelerate.dev']))

        route53.ARecord(self,
                        "Alias_" + domainName,
                        zone=hostedZone,
                        target=route53.RecordTarget.from_alias(
                            targets.CloudFrontTarget(distribution)))
コード例 #7
0
 def __create_route_53_record_group(
     self, route_53_hosted_zone: aws_route53.HostedZone, domain_name: str,
     alternative_domain_names: List[str],
     cloud_front_distribution: aws_cloudfront.Distribution
 ) -> List[aws_route53.ARecord]:
     domain_names = alternative_domain_names
     domain_names.append(domain_name)
     return [
         aws_route53.RecordSet(
             self,
             domain_name.replace('.', '').upper(),
             record_type=aws_route53.RecordType.A,
             zone=route_53_hosted_zone,
             record_name=domain_name,
             target=aws_route53.RecordTarget.from_alias(
                 alias_target=aws_route53_targets.CloudFrontTarget(
                     distribution=cloud_front_distribution)))
         for domain_name in set(domain_names)
     ]
コード例 #8
0
    def __init__(self, scope: core.Construct, id: str, cdnid,
                 **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        prj_name = self.node.try_get_context("project_name")
        env_name = self.node.try_get_context("env")

        hosted_zone = r53.HostedZone(self,
                                     'hosted-zone',
                                     zone_name='cloudevangelist.ca')

        r53.ARecord(self,
                    'cdn-record',
                    zone=hosted_zone,
                    target=r53.RecordTarget.from_alias(
                        alias_target=r53target.CloudFrontTarget(cdnid)),
                    record_name='app')

        ssm.StringParameter(self,
                            'zone-id',
                            parameter_name='/' + env_name + '/zone-id',
                            string_value=hosted_zone.hosted_zone_id)
コード例 #9
0
    def __init__(self, scope: core.Construct, id: str, api: apigateway.RestApi,
                 **kwargs) -> None:
        super().__init__(scope, id, **kwargs)
        stack = core.Stack.of(self)

        bucket = s3.Bucket(self, 'Storage')

        s3_deployment.BucketDeployment(
            self,
            'Deployment',
            sources=[
                s3_deployment.Source.asset('./src/html'),
            ],
            destination_bucket=bucket,
        )

        origin_identity = cloudfront.OriginAccessIdentity(self, 'Identity')

        bucket.grant_read(origin_identity.grant_principal)

        s3_origin = cloudfront.SourceConfiguration(
            s3_origin_source=cloudfront.S3OriginConfig(
                s3_bucket_source=bucket,
                origin_access_identity=origin_identity,
            ),
            behaviors=[
                cloudfront.Behavior(
                    default_ttl=core.Duration.days(1),
                    min_ttl=core.Duration.days(1),
                    max_ttl=core.Duration.days(31),
                    is_default_behavior=True,
                )
            ])

        api_origin = cloudfront.SourceConfiguration(
            origin_path='/{}'.format(api.deployment_stage.stage_name),
            custom_origin_source=cloudfront.CustomOriginConfig(
                domain_name='{}.execute-api.{}.{}'.format(
                    api.rest_api_id, stack.region, stack.url_suffix), ),
            behaviors=[
                cloudfront.Behavior(default_ttl=core.Duration.seconds(0),
                                    min_ttl=core.Duration.seconds(0),
                                    max_ttl=core.Duration.seconds(0),
                                    path_pattern='/stock/*',
                                    forwarded_values={
                                        'query_string': True,
                                        'query_string_cache_keys':
                                        ['start', 'end']
                                    })
            ])

        domain_name = 'demo.training'
        subdomain = 'finance.{}'.format(domain_name)

        zone = route53.HostedZone.from_lookup(
            self,
            'Zone',
            domain_name=domain_name,
        )

        certificate = acm.DnsValidatedCertificate(
            self,
            'Certificate',
            domain_name=subdomain,
            hosted_zone=zone,
            region='us-east-1',
        )

        distribution = cloudfront.CloudFrontWebDistribution(
            self,
            'CDN',
            price_class=cloudfront.PriceClass.PRICE_CLASS_ALL,
            origin_configs=[
                s3_origin,
                api_origin,
            ],
            alias_configuration=cloudfront.AliasConfiguration(
                acm_cert_ref=certificate.certificate_arn,
                names=[subdomain],
            ))

        route53.ARecord(
            self,
            'DnsRecord',
            record_name=subdomain,
            target=route53.AddressRecordTarget.from_alias(
                alias_target=route53_targets.CloudFrontTarget(distribution)),
            zone=zone,
        )
コード例 #10
0
    def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        # Message timeout; used by SQS and Lambda
        message_timeout = core.Duration.seconds(15)

        # SQS queue that the Raspberry Pi will write to
        queue = sqs.Queue(
            self,
            'Queue',
            visibility_timeout=message_timeout,
            receive_message_wait_time=core.Duration.seconds(20),
            retention_period=core.Duration.hours(1),
        )

        # DynamoDB table that the web app will read from
        icao_address = dynamodb.Attribute(
            name='IcaoAddress',
            type=dynamodb.AttributeType.STRING,
        )
        table = dynamodb.Table(
            self,
            'Table',
            partition_key=icao_address,
            billing_mode=dynamodb.BillingMode.PAY_PER_REQUEST,
            removal_policy=core.RemovalPolicy.DESTROY,
        )

        database = timestream.CfnDatabase(
            self,
            'Database',
            database_name='aircraft-database',
        )
        table2 = timestream.CfnTable(self,
                                     'Table2',
                                     database_name=database.ref,
                                     table_name='aircraft-table',
                                     retention_properties={
                                         'MemoryStoreRetentionPeriodInHours':
                                         1,
                                         'MagneticStoreRetentionPeriodInDays':
                                         1,
                                     })

        # IAM user for the Raspberry Pi
        user = iam.User(self, 'RaspberryPi')
        queue.grant_send_messages(user)
        access_key = iam.CfnAccessKey(
            self,
            'AccessKey',
            user_name=user.user_name,
        )

        # IAM role for Lambda function, so it can write to DynamoDB
        lambda_role = iam.Role(
            self,
            'LambdaRole',
            assumed_by=iam.ServicePrincipal('lambda.amazonaws.com'),
            managed_policies=[
                iam.ManagedPolicy.from_aws_managed_policy_name(
                    'service-role/AWSLambdaBasicExecutionRole'),
            ],
        )
        lambda_role.add_to_policy(
            iam.PolicyStatement(
                actions=[
                    'timestream:CancelQuery', 'timestream:DescribeEndpoints',
                    'timestream:DescribeTable', 'timestream:ListMeasures',
                    'timestream:Select', 'timestream:WriteRecords'
                ],
                resources=['*'],  # TODO: narrow down permissions
            ))
        table.grant_read_write_data(lambda_role)

        # Integration between SQS and Lambda
        event = lambda_event_sources.SqsEventSource(
            queue=queue,
            batch_size=10,
        )

        # Lambda function that processes messages from SQS queue and updates DynamoDB table
        import_function = lambda_.Function(
            self,
            'ImportFunction',
            description='Reads SQS messages and writes to DynamoDB',
            runtime=lambda_.Runtime.PYTHON_3_8,
            code=lambda_.Code.from_asset('lambda_import/'),
            timeout=message_timeout,
            handler='index.handler',
            role=lambda_role,
            events=[event],
            environment={
                'TABLE_NAME': table2.ref,
            },
        )

        # TODO: add custom log group
        # TODO: add metric filters for number of succesfull updates and failed updates

        # Lambda function that reads from DynamoDB and returns data to API Gateway
        api_function = lambda_.Function(
            self,
            'ApiFunction',
            description='Reads from DynamoDB and returns to API GW',
            runtime=lambda_.Runtime.PYTHON_3_8,
            code=lambda_.Code.from_asset('lambda_api/'),
            timeout=message_timeout,
            handler='index.handler',
            role=lambda_role,
            environment={
                'TABLE_NAME': table.table_name,
            },
        )

        # API Gateway for requesting aircraft data
        api = apigateway.RestApi(
            self,
            'Api',
            endpoint_types=[apigateway.EndpointType.REGIONAL],
            cloud_watch_role=False,
        )

        aircraft_resource = api.root.add_resource('aircraft')

        aircraft_resource.add_method(
            http_method='GET',
            integration=apigateway.LambdaIntegration(
                api_function,
                proxy=True,
            ),
        )

        # Static website
        bucket = s3.Bucket(self, 'StaticWebsite')

        s3_deployment.BucketDeployment(
            self,
            'Deployment',
            sources=[
                s3_deployment.Source.asset('html/'),
            ],
            destination_bucket=bucket,
        )

        # Permissions between CloudFront and S3
        origin_identity = cloudfront.OriginAccessIdentity(self, 'Identity')
        bucket.grant_read(origin_identity.grant_principal)

        # CloudFront distribution pointing to both S3 and API Gateway
        s3_origin = cloudfront.SourceConfiguration(
            s3_origin_source=cloudfront.S3OriginConfig(
                s3_bucket_source=bucket,
                origin_access_identity=origin_identity,
            ),
            behaviors=[
                cloudfront.Behavior(
                    default_ttl=core.Duration.days(0),
                    min_ttl=core.Duration.days(0),
                    max_ttl=core.Duration.days(31),
                    is_default_behavior=True,
                )
            ])

        api_origin = cloudfront.SourceConfiguration(
            origin_path='/{}'.format(api.deployment_stage.stage_name),
            custom_origin_source=cloudfront.CustomOriginConfig(
                domain_name='{}.execute-api.{}.{}'.format(
                    api.rest_api_id, self.region, self.url_suffix), ),
            behaviors=[
                cloudfront.Behavior(
                    default_ttl=core.Duration.seconds(0),
                    min_ttl=core.Duration.seconds(0),
                    max_ttl=core.Duration.seconds(0),
                    path_pattern='/aircraft/*',
                )
            ])

        domain_name = self.node.try_get_context('domain_name')

        # If domain name is specified, create a certificate and alias configuration for CloudFront
        if domain_name is None:
            alias_configuration = None
        else:
            subdomain = 'aircraft.{}'.format(domain_name)

            zone = route53.HostedZone.from_lookup(
                self,
                'Zone',
                domain_name=domain_name,
            )

            certificate = acm.DnsValidatedCertificate(
                self,
                'Certificate',
                domain_name=subdomain,
                hosted_zone=zone,
                region='us-east-1',
            )

            alias_configuration = cloudfront.AliasConfiguration(
                acm_cert_ref=certificate.certificate_arn,
                names=[subdomain],
            )

        distribution = cloudfront.CloudFrontWebDistribution(
            self,
            'CDN',
            price_class=cloudfront.PriceClass.PRICE_CLASS_ALL,
            alias_configuration=alias_configuration,
            origin_configs=[
                s3_origin,
                api_origin,
            ],
        )

        # If domain name is specified, create a DNS record for CloudFront
        if domain_name is not None:
            route53.ARecord(
                self,
                'DnsRecord',
                record_name=subdomain,
                target=route53.AddressRecordTarget.from_alias(
                    alias_target=route53_targets.CloudFrontTarget(
                        distribution)),
                zone=zone,
            )

        # Outputs that are needed on the Raspberry Pi
        core.CfnOutput(
            self,
            'QueueUrl',
            value=queue.queue_url,
        )
        core.CfnOutput(
            self,
            'AccessKeyId',
            value=access_key.ref,
        )
        core.CfnOutput(
            self,
            'SecretAccessKey',
            value=access_key.attr_secret_access_key,
        )
        core.CfnOutput(
            self,
            'Region',
            value=self.region,
        )
コード例 #11
0
    def __init__(self, scope: core.Construct, construct_id: str,
                 **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        # certificate = certmgr.DnsValidatedCertificate(self,
        #     'HostedZoneCertificate',
        #     hosted_zone=hosted_zone,
        #     domain_name='untermuller.ch',
        #     region='us-east-1',
        #     subject_alternative_names=['resume.untermuller.ch','www.resume.untermuller.ch','www.untermuller.ch']
        #     )

        # website_bucket_create = s3.Bucket(self, 'WebsiteBucketCDK',
        #     bucket_name='BUCKET_NAME',
        #     website_index_document='index.html',
        #     website_error_document='error.html',
        #     public_read_access=True)

        table = dynamo.Table(self,
                             'HitCounter',
                             partition_key={
                                 'name': 'id',
                                 'type': dynamo.AttributeType.STRING
                             })

        counter = lmb.Function(
            self,
            'CounterHandler',
            runtime=lmb.Runtime.PYTHON_3_8,
            handler='counter.lambda_handler',
            code=lmb.Code.asset('resume_cdk/lambda'),
            environment={'TABLE_NAME': table.table_name},
        )

        lambdaapigw = apigw.LambdaRestApi(self, 'Endpoint', handler=counter)

        endpoint = core.CfnOutput(self, 'ApiEndpoint', value=lambdaapigw.url)

        table.grant_read_write_data(counter)

        website_bucket = s3.Bucket.from_bucket_name(self,
                                                    'BUCKET_NAME',
                                                    bucket_name='BUCKET_NAME')

        deploy_website = s3_deploy.BucketDeployment(
            self,
            'DeployWebsiteCDK',
            sources=[s3_deploy.Source.asset("./website")],
            destination_bucket=website_bucket)

        hosted_zone = route53.HostedZone.from_hosted_zone_attributes(
            self, 'HOST.CH', hosted_zone_id='HOST_ID', zone_name='HOST.CH')

        certificate = certmgr.Certificate.from_certificate_arn(
            self, 'CERT_HOST.CH', 'CERT_HOST.CH_ARN')

        cdf_OAI = cdf.OriginAccessIdentity(self, 'OAI-user-s3', comment='OAI')

        grant_access = website_bucket.grant_read(cdf_OAI.grant_principal)

        s3_origin = cdf.S3OriginConfig(
            s3_bucket_source=website_bucket,
            origin_access_identity=cdf_OAI,
        )

        cdf_viewer_policy = cdf.ViewerProtocolPolicy('REDIRECT_TO_HTTPS')

        cdf_behavior = cdf.Behavior(is_default_behavior=True)

        cdf_source_config = cdf.SourceConfiguration(
            behaviors=[cdf_behavior],
            s3_origin_source=s3_origin,
        )

        cdf_dist = cdf.CloudFrontWebDistribution(
            self,
            'ResumeDistribution',
            origin_configs=[cdf_source_config],
            viewer_certificate=cdf.ViewerCertificate.from_acm_certificate(
                certificate,
                aliases=['HOST.CH', 'ALIAS_HOST.CH'],
                security_policy=cdf.SecurityPolicyProtocol.TLS_V1,
                ssl_method=cdf.SSLMethod.SNI),
            viewer_protocol_policy=cdf_viewer_policy)

        route_Aname = route53.ARecord(
            self,
            'ANAME',
            record_name='HOST.CH',
            target=route53.RecordTarget.from_alias(
                route53_targets.CloudFrontTarget(cdf_dist)),
            zone=hosted_zone,
            comment="insert a record")
コード例 #12
0
    def __init__(
        self,
        scope: core.Construct,
        id: str,
        **kwargs,
    ) -> None:
        super().__init__(scope, id, **kwargs)

        s3_domain_prefix = scope.static_site_bucket.bucket_name
        s3_domain_suffix = ".s3-website-us-east-1.amazonaws.com"
        s3_website_domain_name = s3_domain_prefix + s3_domain_suffix

        path_patterns = ["/api/*", "/admin/*", "/flower*"]

        self.distribution = cloudfront.CloudFrontWebDistribution(
            self,
            "CloudFrontDistribution",
            origin_configs=[
                cloudfront.SourceConfiguration(
                    custom_origin_source=cloudfront.CustomOriginConfig(
                        domain_name=scope.alb.load_balancer_dns_name,
                        origin_protocol_policy=MATCH_VIEWER,
                    ),
                    behaviors=[
                        cloudfront.Behavior(
                            allowed_methods=ALL_METHODS,
                            path_pattern=path_pattern,
                            forwarded_values={
                                "headers": ["*"],
                                "cookies": {
                                    "forward": "all"
                                },
                                "query_string": True,
                            },
                        ) for path_pattern in path_patterns
                    ],
                ),
                cloudfront.SourceConfiguration(
                    custom_origin_source=cloudfront.CustomOriginConfig(
                        domain_name=s3_website_domain_name,
                        origin_protocol_policy=HTTP_ONLY,
                    ),
                    behaviors=[
                        cloudfront.Behavior(
                            is_default_behavior=True,
                            cached_methods=GET_HEAD,
                        )
                    ],
                ),
                cloudfront.SourceConfiguration(
                    s3_origin_source=cloudfront.S3OriginConfig(
                        s3_bucket_source=scope.backend_assets_bucket),
                    behaviors=[
                        cloudfront.Behavior(
                            allowed_methods=ALL_METHODS,
                            forwarded_values={"query_string": True},
                            path_pattern=path_pattern,
                            min_ttl=core.Duration.seconds(0),
                            default_ttl=core.Duration.seconds(0),
                            max_ttl=core.Duration.seconds(0),
                        ) for path_pattern in ["/static/*", "/media/*"]
                    ],
                ),
            ],
            alias_configuration=cloudfront.AliasConfiguration(
                acm_cert_ref=scope.certificate.certificate_arn,
                names=[scope.full_domain_name],
            ),
        )

        route53.ARecord(
            self,
            "AliasRecord",
            target=route53.AddressRecordTarget.from_alias(
                targets.CloudFrontTarget(self.distribution)),
            zone=scope.hosted_zone,
            record_name=f"{scope.full_domain_name}.",
        )
コード例 #13
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)
                        )
コード例 #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, id: str,
                 props: StaticSiteProps) -> None:
        super().__init__(scope, id)

        site_domain: str = "{sub_domain}.{domain_name}".format(
            sub_domain=props.site_sub_domain, domain_name=props.domain_name)

        # Content Bucket
        site_bucket = s3.Bucket(
            self,
            "SiteBucket",
            bucket_name=site_domain,
            website_index_document="index.html",
            website_error_document="error.html",
            public_read_access=True,
        )
        core.CfnOutput(self, "Bucket", value=site_bucket.bucket_name)

        # Pre-existing ACM Certificate, with ARN stored in an SSM Parameter
        certificate_arn: str = ssm.StringParameter.from_string_parameter_attributes(
            self,
            "MYCertArnString",
            parameter_name="CertificateArn-{}".format(props.domain_name),
        ).string_value

        # CloudFront distribution that provides HTTPS
        alias_configuration = cloudfront.AliasConfiguration(
            acm_cert_ref=certificate_arn,
            names=[site_domain],
            ssl_method=cloudfront.SSLMethod.SNI,
            security_policy=cloudfront.SecurityPolicyProtocol.TLS_V1_1_2016,
        )

        source_configuration = cloudfront.SourceConfiguration(
            s3_origin_source=cloudfront.S3OriginConfig(
                s3_bucket_source=site_bucket),
            behaviors=[cloudfront.Behavior(is_default_behavior=True)],
        )

        distribution = cloudfront.CloudFrontWebDistribution(
            self,
            "SiteDistribution",
            alias_configuration=alias_configuration,
            origin_configs=[source_configuration],
        )
        core.CfnOutput(self,
                       "DistributionId",
                       value=distribution.distribution_id)

        # Route53 alias record for the CloudFront Distribution
        zone = route53.HostedZone.from_hosted_zone_attributes(
            self,
            id="HostedZoneID",
            hosted_zone_id=props.hosted_zone_id,
            zone_name=props.domain_name,
        )

        route53.ARecord(
            self,
            "SiteAliasRecord",
            record_name=site_domain,
            target=route53.AddressRecordTarget.from_alias(
                targets.CloudFrontTarget(distribution)),
            zone=zone,
        )
コード例 #16
0
class TsWwwStack(core.Stack):

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

        # Materialize existing AWS Hosted DNS Zone
        dns_zone = r53_.HostedZone.from_lookup(self,"dns_zone",domain_name = domain_name)
        
        # Compose site name for AWS Certificate
        site_fqdn = "www." + dns_zone.zone_name

        # Create a DNS Certificate
        certificate = cm_.DnsValidatedCertificate (self,"certificate",
                                                         domain_name=site_fqdn,
                                                         hosted_zone=dns_zone,
                                                         region="us-east-1")

        # Define Bucket to store Site Contents
        ts_www_bucket = s3_.Bucket(self,"truesys-static-website",
                                        bucket_name = site_fqdn,
                                        website_index_document = "index.html",
                                        website_error_document = "404/index.html",
                                        public_read_access = True
                                        )

        #Cria lambda function para fazr URL Rewriting de default document
        url_rewrite_lambda = _lambda.Function(self,'URLRewriteLambdaEdge',
                                                   handler='url_rewrite_handler.handler',
                                                   runtime=_lambda.Runtime.PYTHON_3_7,
                                                   code=_lambda.Code.asset('lambda_edge'),
        )
        
        
        // A numbered version to give to cloudfront
       const myOriginRequestHandlerVersion = new lambda.Version(this, "OriginRequestHandlerVersion", {
               lambda: myOriginRequestHandler,
});
        
        
        lea = clf_.AlambdaFunctionAssociation(event_type = cfl_AlambdaEdgeEventType.ORIGIN_REQUEST, myOriginRequestHandlerVersion)
        
        #Define Cloud Front distribution
        s3_origin_config = clf_.S3OriginConfig(s3_bucket_source = ts_www_bucket)
        behaviour = clf_.Behavior(is_default_behavior=True, 
                                  lambda_function_associations = [lea])
        source_config = clf_.SourceConfiguration(s3_origin_source=s3_origin_config,
                                                 behaviors = [behaviour])
        clf_alias_config = clf_.AliasConfiguration(acm_cert_ref = certificate.certificate_arn,
                                                  names=[site_fqdn], 
                                                  ssl_method = clf_.SSLMethod.SNI,
                                                  security_policy = clf_.SecurityPolicyProtocol.TLS_V1_1_2016)
        cf_distribution = clf_.CloudFrontWebDistribution(self,"TsDistribution",
                                                           origin_configs=[source_config],
                                                           alias_configuration=clf_alias_config,
                                                           price_class = clf_.PriceClass.PRICE_CLASS_ALL
                                                     )
                                                     
        #Define Route 53 Alias aka endereco do site
        cloud_front_target = r53tgs_.CloudFrontTarget(distribution = cf_distribution) 
        r53_target = r53_.RecordTarget.from_alias(alias_target = cloud_front_target)
        r53_.ARecord(self,"EnderecoDosite",record_name = site_fqdn,
                                           target = r53_target,
                                           zone = dns_zone)
        
        
        #Faz deploy do conteudo do site para o S3 e invalida distribution
        site_assets = s3deploy_.Source.asset("./true-systems-static-site/public")
        s3deploy_.BucketDeployment(self,"truesys-website-content-deployment",
                                        sources = [site_assets],
                                        destination_bucket=ts_www_bucket,
                                        distribution=cf_distribution,
                                        distribution_paths = [ "/*"])

        core.CfnOutput(self,"Site",value = site_fqdn)                                
コード例 #17
0
    def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        # define fully qualified domain name for website
        site_domain = '{sub}.{zone}'.format(sub=WEBSITE_SUBDOMAIN,
                                            zone=DNS_ZONE_NAME)

        # create an s3 bucket to hold the static site
        bucket = s3.Bucket(
            self,
            'RootBucket',
            bucket_name=site_domain,
            website_index_document='index.html',
            website_error_document='404.html',
            public_read_access=True,
            versioned=False,
            removal_policy=core.RemovalPolicy.
            DESTROY,  # this refers to the case where a stack is destroyed, where we
            # want to destroy the static site bucket as well
        )

        # establish the route53 domain name
        dns_zone = r53.HostedZone.from_lookup(self,
                                              'WebsiteZone',
                                              domain_name='jeichenhofer.com')
        core.CfnOutput(self, 'site_address', value='https://' +
                       site_domain)  # output the address to cloudformation

        # create a tls certificate
        cert_arn = acm.DnsValidatedCertificate(
            self,
            'SiteCertificate',
            domain_name=site_domain,
            hosted_zone=dns_zone,
        ).certificate_arn
        core.CfnOutput(self, 'site_cert', value=cert_arn)

        # create CloudFront distro for https and caching
        dist = cloudfront.CloudFrontWebDistribution(
            self,
            'SiteDistribution',
            alias_configuration={
                "acmCertRef": cert_arn,
                "names": [site_domain],
                "sslMethod": cloudfront.SSLMethod.SNI,
                "securityPolicy":
                cloudfront.SecurityPolicyProtocol.TLS_V1_2_2018
            },
            origin_configs=[{
                "s3OriginSource": {
                    "s3BucketSource": bucket
                },
                "behaviors": [{
                    "isDefaultBehavior": True
                }],
            }])
        core.CfnOutput(self, 'distribution_id', value=dist.distribution_id)

        # point the domain name to the cloudfront distribution
        r53.ARecord(self,
                    'SiteAliasRecord',
                    zone=dns_zone,
                    record_name=site_domain,
                    target=r53.AddressRecordTarget.from_alias(
                        r53_targets.CloudFrontTarget(dist)))

        # deploy the static files to the bucket
        s3deploy.BucketDeployment(
            self,
            'DeployWithInvalidation',
            sources=[s3deploy.Source.asset('./site-contents')],
            destination_bucket=bucket,
            distribution=dist,
            distribution_paths=['/*'],
        )
    def __init__(self, scope: core.Construct, id: str,
                 props: StaticSiteProps) -> None:
        super().__init__(scope, id)

        fqdn = props.fqdn
        certificate_arn = props.certificate_arn
        error_configuration = props.error_configuration

        if len(error_configuration) == 0:
            error_codes = None
        else:
            error_codes = []
            for error_config in error_configuration:
                error_codes.append(
                    cloudfront.CfnDistribution.CustomErrorResponseProperty(
                        error_code=error_config["error_code"],
                        error_caching_min_ttl=error_config[
                            "error_caching_min_ttl"],
                        response_code=error_config["response_code"],
                        response_page_path=error_config["response_page_path"],
                    ))

        # Content Bucket
        site_bucket = s3.Bucket(
            self,
            "SiteBucket",
            bucket_name=fqdn + "-static-site",
            website_index_document="index.html",
            website_error_document="index.html",
            block_public_access=s3.BlockPublicAccess(block_public_policy=True),
            removal_policy=core.RemovalPolicy.DESTROY,
        )
        self.bucket_name = fqdn + "-static-site"
        self.bucket_resource = site_bucket
        origin_access_identity = cloudfront.CfnCloudFrontOriginAccessIdentity(
            self,
            "OriginIdentity",
            cloud_front_origin_access_identity_config={
                "comment": "Allow CloudFront to access web site"
            },
        )
        # Create IAM policy for S3 Canonical User
        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(site_bucket.bucket_arn)
        policy_statement.add_resources(f"{site_bucket.bucket_arn}/*")
        policy_statement.add_canonical_user_principal(
            origin_access_identity.attr_s3_canonical_user_id)
        site_bucket.add_to_resource_policy(policy_statement)
        core.CfnOutput(self, "Bucket", value=site_bucket.bucket_name)

        # CloudFront distribution with or without certificate
        source_configuration = cloudfront.SourceConfiguration(
            s3_origin_source=cloudfront.S3OriginConfig(
                s3_bucket_source=site_bucket,
                origin_access_identity_id=origin_access_identity.ref,
            ),
            behaviors=[cloudfront.Behavior(is_default_behavior=True)],
        )
        # Use ACM Certificate if provided, otherwise no-SSL
        if certificate_arn:
            # CloudFront distribution that provides HTTPS
            alias_configuration = cloudfront.AliasConfiguration(
                acm_cert_ref=certificate_arn,
                names=[fqdn],
                ssl_method=cloudfront.SSLMethod.SNI,
                security_policy=cloudfront.SecurityPolicyProtocol.
                TLS_V1_1_2016,
            )
            distribution = cloudfront.CloudFrontWebDistribution(
                self,
                "SiteDistribution",
                alias_configuration=alias_configuration,
                error_configurations=error_codes,
                origin_configs=[source_configuration],
                viewer_protocol_policy=cloudfront.ViewerProtocolPolicy.
                REDIRECT_TO_HTTPS,
            )
        else:
            distribution = cloudfront.CloudFrontWebDistribution(
                self,
                "SiteDistribution",
                origin_configs=[source_configuration],
                error_configurations=error_codes,
            )
        core.CfnOutput(
            self,
            "DistributionId",
            value=distribution.distribution_id,
            export_name=props.output_name,
        )

        # Route53 alias record for the CloudFront Distribution
        zone = route53.HostedZone.from_hosted_zone_attributes(
            self,
            id="HostedZoneID",
            hosted_zone_id=props.hosted_zone_id,
            zone_name=props.fqdn,
        )

        route53.ARecord(
            self,
            "SiteAliasRecord",
            record_name=fqdn,
            target=route53.AddressRecordTarget.from_alias(
                targets.CloudFrontTarget(distribution)),
            zone=zone,
        )
コード例 #19
0
    def web(self):
        zone = route53.HostedZone.from_hosted_zone_attributes(
            self,
            'hosted_zone',
            hosted_zone_id=HOSTED_ZONE_ID,
            zone_name=self.zone)
        cert = cert_manager.DnsValidatedCertificate(
            self,
            'domain_cert',
            domain_name=self.zone,
            subject_alternative_names=[
                self.web_domain
            ],
            hosted_zone=zone,
            validation_method=cert_manager.ValidationMethod.DNS)
        # cert = cert_manager.Certificate.from_certificate_arn(self, 'certificateDomainForAll',
        #                                                      "arn:aws:acm:us-east-1:134764946504:certificate/f74613d7-8cc5-4de1-a2ed-467d5321839d")
        site_bucket = s3.Bucket(self, 'site_bucket',
                                bucket_name=self.web_domain,
                                website_index_document='index.html',
                                website_error_document='404.html',
                                public_read_access=True)
        core.CfnOutput(self, 'bucket_name', value=site_bucket.bucket_name)
        source_behavior = cloudfront.Behavior(
            is_default_behavior=True,
            cached_methods=cloudfront.CloudFrontAllowedCachedMethods.GET_HEAD_OPTIONS,
            allowed_methods=cloudfront.CloudFrontAllowedMethods.GET_HEAD_OPTIONS,
            compress=True)
        s3_origin_source = cloudfront.S3OriginConfig(s3_bucket_source=site_bucket)
        origin_source_config = cloudfront.SourceConfiguration(
            s3_origin_source=s3_origin_source,
            behaviors=[source_behavior])
        alias_configuration = cloudfront.AliasConfiguration(
            acm_cert_ref=cert.certificate_arn,
            names=[self.zone],
            ssl_method=cloudfront.SSLMethod.SNI,
            security_policy=cloudfront.SecurityPolicyProtocol.TLS_V1_2_2019)

        distribution = cloudfront.CloudFrontWebDistribution(
            self, 'cf-web-distro',
            alias_configuration=alias_configuration,
            origin_configs=[origin_source_config],
            error_configurations=[
                cloudfront.CfnDistribution.CustomErrorResponseProperty(
                    error_code=404,
                    response_code=404,
                    response_page_path='/404.html'
                ),
                cloudfront.CfnDistribution.CustomErrorResponseProperty(
                    error_code=403,
                    response_code=404,
                    response_page_path='/404.html',
                )
            ],
            http_version=cloudfront.HttpVersion.HTTP2,
            viewer_protocol_policy=cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS
        )

        core.CfnOutput(self, 'Distribution ID', value=distribution.distribution_id)
        core.CfnOutput(self, 'Distribution domain name', value=distribution.domain_name)
        core.CfnOutput(self, 'SiteBucketWebsiteDomain', value=site_bucket.bucket_website_domain_name)
        # noinspection PyTypeChecker
        target_alias = route53.RecordTarget.from_alias(targets.CloudFrontTarget(distribution))
        route53.ARecord(self, 'arecord-web',
                        record_name=self.zone,
                        target=target_alias,
                        zone=zone,
                        ttl=core.Duration.minutes(60))
        s3_deployment.BucketDeployment(self, "deploy-with-invalidation",
                                       sources=[
                                           s3_deployment.Source.asset('./../website')
                                       ],
                                       destination_bucket=site_bucket,
                                       distribution=distribution,
                                       content_language='en-US',
                                       distribution_paths=['/*'])
コード例 #20
0
    def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        # set variables for site s3 bucket
        bucket_name = DOMAIN_WEBSITE['bucket_name']
        website_index = DOMAIN_WEBSITE['website_index']
        website_error = DOMAIN_WEBSITE['website_error']
        website_code_folder = DOMAIN_WEBSITE['website_code_folder']
        site_domain = DOMAIN_WEBSITE['site_domain']
        certificate_domain = DOMAIN_WEBSITE['certificate_domain']
        api_domain = DOMAIN_WEBSITE['api_domain']
        hosted_zone_name = DOMAIN_WEBSITE['hosted_zone_name']
        hosted_zone_id = DOMAIN_WEBSITE['hosted_zone_id']

        #self.lambda_code = aws_lambda.Code.from_cfn_parameters()

        # retrieve hosted zone
        hosted_zone = aws_route53.HostedZone.from_hosted_zone_attributes(
            self,
            'hostedZone',
            hosted_zone_id=hosted_zone_id,
            zone_name=hosted_zone_name)

        # set variables for backend
        lambda_code_location = "jukebike/backend/"

        # Construct code goes here
        CfnOutput(self, "Site", value=f"https://{site_domain}")

        # Content bucket
        site_bucket = aws_s3.Bucket(self,
                                    "websitebucket",
                                    bucket_name=bucket_name,
                                    website_index_document=website_index,
                                    website_error_document=website_error,
                                    public_read_access=True,
                                    removal_policy=RemovalPolicy.DESTROY)
        CfnOutput(self, "BucketArn", value=site_bucket.bucket_arn)
        CfnOutput(self, "WebsiteUrl", value=site_bucket.bucket_website_url)

        # Certificate
        cert = aws_certificatemanager.DnsValidatedCertificate(
            self,
            "certificate_website",
            domain_name=site_domain,
            hosted_zone=hosted_zone,
            region="us-east-1")
        CfnOutput(self, 'CertificateArn', value=cert.certificate_arn)

        distr = CloudFrontWebDistribution(
            self,
            "SiteDistribution",
            alias_configuration=AliasConfiguration(
                acm_cert_ref=cert.certificate_arn,
                names=[site_domain],
                ssl_method=aws_cloudfront.SSLMethod.SNI,
                security_policy=aws_cloudfront.SecurityPolicyProtocol.
                TLS_V1_1_2016,
            ),
            origin_configs=[
                SourceConfiguration(
                    s3_origin_source=aws_cloudfront.S3OriginConfig(
                        s3_bucket_source=site_bucket),
                    behaviors=[
                        aws_cloudfront.Behavior(is_default_behavior=True)
                    ])
            ])
        CfnOutput(self, "DistributionId", value=distr.distribution_id)
        #
        # Route 53 alias record for the cloudfront distribution
        aws_route53.ARecord(self,
                            "SiteAliasRecord",
                            zone=hosted_zone,
                            target=aws_route53.AddressRecordTarget.from_alias(
                                aws_route53_targets.CloudFrontTarget(distr)),
                            record_name=site_domain)

        aws_s3_deployment.BucketDeployment(
            self,
            "DeployWithInvalidation",
            sources=[aws_s3_deployment.Source.asset(website_code_folder)],
            destination_bucket=site_bucket,
            distribution=distr,
            distribution_paths=["/*"])

        ########################### Backend #################

        certificate = aws_certificatemanager.DnsValidatedCertificate(
            self,
            "domaincertificate",
            hosted_zone=hosted_zone,
            region='us-east-1',
            domain_name=certificate_domain,
            validation_method=aws_certificatemanager.ValidationMethod.DNS)

        ############# Search API ###################

        search_lambda = aws_lambda.Function(
            self,
            "SearchLambda",
            code=aws_lambda.Code.from_asset(lambda_code_location),
            handler="search.handler",
            runtime=aws_lambda.Runtime.PYTHON_3_7)

        CfnOutput(self, "SearchLambda_", value=search_lambda.function_arn)

        search_api = aws_apigateway.LambdaRestApi(
            self,
            'SearchSpotifyEndpoint',
            handler=search_lambda,
        )

        ############# Whats-Next API ###################
        whats_next_lambda = aws_lambda.Function(
            self,
            "WhatsNextLambda",
            code=aws_lambda.Code.from_asset(lambda_code_location),
            handler="whats_next.handler",
            runtime=aws_lambda.Runtime.PYTHON_3_7)
        CfnOutput(self,
                  "WhatsNextLambda_",
                  value=whats_next_lambda.function_arn)

        whats_next_api = aws_apigateway.LambdaRestApi(
            self,
            'WhatsNextEndpoint',
            handler=whats_next_lambda,
        )

        ############# Whats-Next API ###################
        wish_track_lambda = aws_lambda.Function(
            self,
            "WishTrackLambda",
            code=aws_lambda.Code.from_asset(lambda_code_location),
            handler="wish_track.handler",
            runtime=aws_lambda.Runtime.PYTHON_3_7)
        CfnOutput(self,
                  "WishTrackLambda_",
                  value=wish_track_lambda.function_arn)

        wish_track_api = aws_apigateway.LambdaRestApi(
            self,
            'WishTrackEndpoint',
            handler=wish_track_lambda,
        )

        ################## Publish APIS with custom domain name ##############
        # Pre-Requirements:
        # [Manual] 1) Registered Domain with Route 53 (e.g. jacubasch.com)
        # 2) Certificate in North Virgina for domain (e.g. api.jacubasch.com) -> AWS Certification Manager
        # 3) API Gateway Custom Domain with Edge
        # 4) Alias-Record in Route53 forwarding to Cloudfront Target Domain Name (can be found in API Gateway)
        # TODO: in separaten Base-Stack auslagern?
        # https://medium.com/@maciejtreder/custom-domain-in-aws-api-gateway-a2b7feaf9c74

        domain = aws_apigateway.DomainName(
            self,
            'searchDomain',
            certificate=certificate,
            endpoint_type=aws_apigateway.EndpointType.EDGE,
            domain_name=api_domain)
        domain.add_base_path_mapping(target_api=search_api, base_path="search")
        domain.add_base_path_mapping(target_api=whats_next_api,
                                     base_path="whats-next")
        domain.add_base_path_mapping(target_api=wish_track_api,
                                     base_path="wish-track")

        target = aws_route53_targets.ApiGatewayDomain(domain)
        record_target = aws_route53.RecordTarget.from_alias(target)
        alias_record = aws_route53.ARecord(self,
                                           'aliasRecord',
                                           target=record_target,
                                           record_name=api_domain,
                                           zone=hosted_zone)

        CfnOutput(self, "AliasRecord_", value=alias_record.to_string())

        ################## Dynamo DB ##############

        # create dynamo table
        track_table = aws_dynamodb.Table(
            self,
            "track_table",
            partition_key=aws_dynamodb.Attribute(
                name="track_uri", type=aws_dynamodb.AttributeType.STRING))

        # grant permission to lambda  & provide environment variable
        track_table.grant_write_data(wish_track_lambda)
        wish_track_lambda.add_environment("TRACK_TABLE_NAME",
                                          track_table.table_name)

        track_table.grant_read_write_data(whats_next_lambda)
        whats_next_lambda.add_environment("TRACK_TABLE_NAME",
                                          track_table.table_name)
コード例 #21
0
    def __init__(self, scope: core.Construct, id: str, sub_domain: str, domain: str, **kwargs) -> None:
        """
        StaticSiteStack creates the CloudFormation Stack that creates the resources necessary to host a static web site from an S3 Bucket with a CloudFormation CDN and a custom domain name.  

        arguments:
        sub_domain -- sub domain name used for the dashboard url, acg-covid-challenge
        domain -- custom domain name owned by user, e.g. my-domain.com
        """

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

        # In the GitHub Actions Workflow, the Certificate is created using the CertificateStack and its arn is set as an environment variable
        self.certificate_arn = self.node.try_get_context("certificate_arn")

        bucket = s3.Bucket(self,
                           f"{sub_domain}-bucket",
                           website_index_document="index.html",
                           removal_policy=core.RemovalPolicy.DESTROY,
                           block_public_access=s3.BlockPublicAccess.BLOCK_ALL
                           )

        core.CfnOutput(self, "sitebucketname",
                       value=bucket.bucket_name)

        oai = cf.OriginAccessIdentity(
            self,
            f"OriginIdentity-{sub_domain}",
        )

        alias_configuration = cf.AliasConfiguration(
            acm_cert_ref=self.certificate_arn,
            names=[f"{sub_domain}.{domain}"],
            ssl_method=cf.SSLMethod.SNI,
            security_policy=cf.SecurityPolicyProtocol.TLS_V1_1_2016
        )

        source_config = cf.SourceConfiguration(
            s3_origin_source=cf.S3OriginConfig(
                s3_bucket_source=bucket,
                origin_access_identity=oai
            ),
            behaviors=[cf.Behavior(is_default_behavior=True)]
        )

        cf_dist = cf.CloudFrontWebDistribution(
            self,
            f"{sub_domain}-static-site-distribution",
            alias_configuration=alias_configuration,
            origin_configs=[source_config],
            viewer_protocol_policy=cf.ViewerProtocolPolicy.REDIRECT_TO_HTTPS
        )

        core.CfnOutput(self, "distid", value=cf_dist.distribution_id)

        # Route53 alias record for the CloudFront Distribution
        hosted_zone = route53.HostedZone.from_lookup(
            self, f"{sub_domain}-hosted-zone-id", domain_name=domain)

        route53.ARecord(
            self,
            f'{sub_domain}-alias-record',
            record_name=f"{sub_domain}.{domain}",
            target=route53.AddressRecordTarget.from_alias(
                targets.CloudFrontTarget(cf_dist)),
            zone=hosted_zone
        )
コード例 #22
0
    def __init__(self, scope: core.Construct, id: str, domain: DomainProps,
                 website: WebsiteConstruct, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        zone = route53.HostedZone(self,
                                  'Zone',
                                  zone_name=domain.domain_name,
                                  comment='Managed by CDK')

        root_record_name = domain.domain_name
        wildcard_record_name = '*.{}'.format(root_record_name)

        website_target = route53.AddressRecordTarget.from_alias(
            alias_target=route53_targets.CloudFrontTarget(
                website.distribution))

        route53.ARecord(
            self,
            'RootIpv4',
            record_name=root_record_name,
            zone=zone,
            target=website_target,
        )

        route53.AaaaRecord(
            self,
            'RootIpv6',
            record_name=root_record_name,
            zone=zone,
            target=website_target,
        )

        route53.ARecord(
            self,
            'WildcardIpv4',
            record_name=wildcard_record_name,
            zone=zone,
            target=website_target,
        )

        route53.AaaaRecord(
            self,
            'WildcardIpv6',
            record_name=wildcard_record_name,
            zone=zone,
            target=website_target,
        )

        route53.MxRecord(
            self,
            'Email',
            record_name=root_record_name,
            zone=zone,
            values=domain.mx_record_values,
        )

        route53.TxtRecord(
            self,
            'Text',
            record_name=root_record_name,
            zone=zone,
            values=domain.txt_record_values,
        )
コード例 #23
0
    def __init__(self, scope: core.Construct, id: str, hosted_zone_id: str,
                 hosted_zone_name: str, website_domain_name: str,
                 certificate_in_us_east_1_arn: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        # Raise an exception if we get a certificate that doesn't live in us-east-1
        check_us_east_1_cert(certificate_in_us_east_1_arn)

        # The S3 Bucket that will store our website
        website_bucket = s3.Bucket(self, "WebsiteBucket")

        # The Origin Access Identity is a way to allow CloudFront Access to the Website Bucket
        origin_access_identity = cloudfront.OriginAccessIdentity(
            self,
            "OriginAccessIdentity",
            comment="Allows Read-Access from CloudFront")

        # We tell the website bucket to allow access from CloudFront
        website_bucket.grant_read(origin_access_identity)

        # Import the cert from the arn we get as a parameter
        tls_cert = certificatemanager.Certificate.from_certificate_arn(
            self, "Certificate", certificate_arn=certificate_in_us_east_1_arn)

        # We set up the CloudFront Distribution with the S3 Bucket as the origin and our certificate
        cloudfront_distribution = cloudfront.CloudFrontWebDistribution(
            self,
            "WebsiteDistribution",
            origin_configs=[
                cloudfront.SourceConfiguration(
                    s3_origin_source=cloudfront.S3OriginConfig(
                        s3_bucket_source=website_bucket,
                        origin_access_identity=origin_access_identity),
                    behaviors=[
                        cloudfront.Behavior(is_default_behavior=True,
                                            default_ttl=core.Duration.hours(1))
                    ],
                )
            ],
            error_configurations=[
                # Point CloudFront to our custom 404 error page when a 404 occurs
                cloudfront.CfnDistribution.CustomErrorResponseProperty(
                    error_code=404,
                    response_code=404,
                    response_page_path="/404.html")
            ],
            viewer_certificate=cloudfront.ViewerCertificate.
            from_acm_certificate(certificate=tls_cert,
                                 aliases=[website_domain_name]))

        # Set the DNS Alias for CloudFront
        hosted_zone = route53.HostedZone.from_hosted_zone_attributes(
            self,
            "HostedZone",
            hosted_zone_id=hosted_zone_id,
            zone_name=hosted_zone_name)

        cloudfront_alias_record = route53.ARecord(
            self,
            "DNSAliasForCloudFront",
            zone=hosted_zone,
            target=route53.RecordTarget.from_alias(
                route53_targets.CloudFrontTarget(cloudfront_distribution)),
            record_name=website_domain_name,
        )

        # Repo for the website
        repository = codecommit.Repository(
            self,
            "Repository",
            repository_name=website_domain_name,
            description=f"Repository for the website {website_domain_name}")

        website_build_project = codebuild.PipelineProject(
            self,
            "WebsiteBuild",
            build_spec=codebuild.BuildSpec.from_source_filename(
                "buildspec.yml"),
            environment=codebuild.BuildEnvironment(
                build_image=codebuild.LinuxBuildImage.STANDARD_4_0),
            environment_variables={
                "baseurl":
                codebuild.BuildEnvironmentVariable(
                    value=f"https://{website_domain_name}/"),
                "bucket":
                codebuild.BuildEnvironmentVariable(
                    value=website_bucket.bucket_name)
            })
        website_bucket.grant_read_write(website_build_project.grant_principal)

        source_output = codepipeline.Artifact()

        website_build_pipeline = codepipeline.Pipeline(
            self,
            "WebsiteBuildPipeline",
            stages=[

                # Check Out the Code From the Repo
                codepipeline.StageProps(
                    stage_name="Source",
                    actions=[
                        codepipeline_actions.CodeCommitSourceAction(
                            action_name="CheckoutCode",
                            repository=repository,
                            output=source_output)
                    ]),

                # Build and deploy the Website to S3 (this uses the sync command with the delete option, which the codebuild action to deploy to S3 doesn't support)
                codepipeline.StageProps(
                    stage_name="BuildAndDeploy",
                    actions=[
                        codepipeline_actions.CodeBuildAction(
                            action_name="BuildAndDeployWebsite",
                            project=website_build_project,
                            input=source_output)
                    ])
            ])

        # Display the Repo Clone URLs as the Stack Output
        core.CfnOutput(self,
                       "RepositoryCloneUrlSSH",
                       value=repository.repository_clone_url_ssh)
        core.CfnOutput(self,
                       "RepositoryCloneUrlHTTPS",
                       value=repository.repository_clone_url_http)

        # Display the website URL as the stack output
        core.CfnOutput(self,
                       "WebsiteUrl",
                       value=f"https://{website_domain_name}/")
コード例 #24
0
    def __init__(self, scope: core.Construct, id: str,
                 props: StaticSiteProps) -> None:
        super().__init__(scope, id)

        fqdn = props.fqdn
        certificate_arn = props.certificate_arn
        error_configuration = props.error_configuration

        if len(error_configuration) == 0:
            error_codes = None
        else:
            error_codes = []
            for error_config in error_configuration:
                error_codes.append(
                    cloudfront.CfnDistribution.CustomErrorResponseProperty(
                        error_code=error_config["error_code"],
                        error_caching_min_ttl=error_config[
                            "error_caching_min_ttl"],
                        response_code=error_config["response_code"],
                        response_page_path=error_config["response_page_path"],
                    ))

        # Content Bucket
        site_bucket = s3.Bucket(
            self,
            "SiteBucket",
            bucket_name=fqdn + "-static-site",
            website_index_document="index.html",
            website_error_document="index.html",
            block_public_access=s3.BlockPublicAccess(block_public_policy=True),
            removal_policy=core.RemovalPolicy.DESTROY,
        )
        self.bucket_name = fqdn + "-static-site"
        self.bucket_resource = site_bucket

        # Uses new method for OAI (still breaking changes) - https://github.com/aws/aws-cdk/pull/4491
        origin_access_identity = cloudfront.OriginAccessIdentity(
            self, "OriginIdentity")
        # Add CloudFront Origin Access Identity to the bucket
        site_bucket.grant_read(origin_access_identity)

        core.CfnOutput(self, "Bucket", value=site_bucket.bucket_name)

        # CloudFront distribution with or without certificate
        source_configuration = cloudfront.SourceConfiguration(
            s3_origin_source=cloudfront.S3OriginConfig(
                s3_bucket_source=site_bucket,
                origin_access_identity=origin_access_identity,
            ),
            behaviors=[cloudfront.Behavior(is_default_behavior=True)],
        )
        # Use ACM Certificate if provided, otherwise no-SSL
        if certificate_arn:
            # CloudFront distribution that provides HTTPS
            alias_configuration = cloudfront.AliasConfiguration(
                acm_cert_ref=certificate_arn,
                names=[fqdn],
                ssl_method=cloudfront.SSLMethod.SNI,
                security_policy=cloudfront.SecurityPolicyProtocol.
                TLS_V1_1_2016,
            )
            distribution = cloudfront.CloudFrontWebDistribution(
                self,
                "SiteDistribution",
                alias_configuration=alias_configuration,
                error_configurations=error_codes,
                origin_configs=[source_configuration],
                viewer_protocol_policy=cloudfront.ViewerProtocolPolicy.
                REDIRECT_TO_HTTPS,
            )
        else:
            distribution = cloudfront.CloudFrontWebDistribution(
                self,
                "SiteDistribution",
                origin_configs=[source_configuration],
                error_configurations=error_codes,
            )
        core.CfnOutput(
            self,
            "DistributionId",
            value=distribution.distribution_id,
            export_name=props.output_name,
        )

        # Route53 alias record for the CloudFront Distribution
        zone = route53.HostedZone.from_hosted_zone_attributes(
            self,
            id="HostedZoneID",
            hosted_zone_id=props.hosted_zone_id,
            zone_name=props.fqdn,
        )

        route53.ARecord(
            self,
            "SiteAliasRecord",
            record_name=fqdn,
            target=route53.RecordTarget.from_alias(
                alias_target=targets.CloudFrontTarget(distribution)),
            zone=zone,
        )
コード例 #25
0
    def __init__(self, scope: core.Construct, id: str, **kwargs):
        super().__init__(scope, id, **kwargs)

        # note assumption zone is named after domain
        hosted_zone = route53.HostedZone.from_hosted_zone_attributes(
            self,
            "HostedZone",
            hosted_zone_id=startuptoolbag_config.hosted_zone_id,
            zone_name=startuptoolbag_config.website_domain_name)

        # SSL/TLS Certificate
        # https://github.com/aws/aws-cdk/pull/8552
        # Experimental vs 'Certificate' (which requires validation in the console)
        tls_cert = certificatemanager.DnsValidatedCertificate(
            self,
            "SiteCertificate",
            hosted_zone=hosted_zone,
            domain_name=f'*.{startuptoolbag_config.website_domain_name}',
            subject_alternative_names=[
                startuptoolbag_config.website_domain_name
            ],
            region='us-east-1',
        )

        # Import the bucket that was created outside the stack
        self.www_site_bucket = s3.Bucket.from_bucket_name(
            self, 'SiteBucket', core.Fn.import_value("WWWSITEBUCKETNAME"))

        # CloudFront distribution that provides HTTPS - for www
        www_alias_configuration = cloudfront.AliasConfiguration(
            acm_cert_ref=tls_cert.certificate_arn,
            names=[f'www.{startuptoolbag_config.website_domain_name}'],
            ssl_method=cloudfront.SSLMethod.SNI,
            security_policy=cloudfront.SecurityPolicyProtocol.TLS_V1_1_2016)

        www_source_configuration = cloudfront.SourceConfiguration(
            s3_origin_source=cloudfront.S3OriginConfig(
                s3_bucket_source=self.www_site_bucket),
            behaviors=[cloudfront.Behavior(is_default_behavior=True)])

        www_distribution = cloudfront.CloudFrontWebDistribution(
            self,
            'SiteDistribution',
            alias_configuration=www_alias_configuration,
            origin_configs=[www_source_configuration])

        route53.ARecord(
            self,
            'CloudFrontARecord',
            zone=hosted_zone,
            record_name=
            f'www.{startuptoolbag_config.website_domain_name}',  #site domain
            target=aws_route53.RecordTarget.from_alias(
                aws_route53_targets.CloudFrontTarget(www_distribution)))

        # NAKED site bucket which redirects to naked to www
        redirect = aws_route53_patterns.HttpsRedirect(
            self,
            'NakedRedirect',
            record_names=[startuptoolbag_config.website_domain_name],
            target_domain=f'www.{startuptoolbag_config.website_domain_name}',
            zone=hosted_zone,
            certificate=tls_cert)

        # Create the API Gateway
        self.rest_api = aws_apigateway.RestApi(self,
                                               'RestApiGateway',
                                               deploy=False)
        api_domain_name = f'api.{startuptoolbag_config.website_domain_name}'
        domain = self.rest_api.add_domain_name('APIDomain',
                                               certificate=tls_cert,
                                               domain_name=api_domain_name)

        route53.ARecord(
            self,
            'APIGWAliasRecord',
            zone=hosted_zone,
            record_name=api_domain_name,  #site domain
            target=aws_route53.RecordTarget.from_alias(
                aws_route53_targets.ApiGatewayDomain(domain)))
コード例 #26
0
    def __init__(
        self,
        scope: core.Construct,
        id: str,
        certificate_arn: str,
        hosted_zone_id,
        domain_name,
        **kwargs
    ) -> None:
        super().__init__(scope, id, **kwargs)

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

        # since the bucket has already been created from previous deployments
        # we build the bucket object from attributes here rather than creating a
        # new bucket.
        # This change is required since we had to re-create this entire stack 
        # after the bucket had been originally created.
        site_bucket = s3.Bucket.from_bucket_attributes(
            self,
            "SiteBucket",
            bucket_name=domain_name
        )

        oai = cloudfront.OriginAccessIdentity(self, "OriginAccessIdentity")

        distribution = cloudfront.CloudFrontWebDistribution(
            self,
            "SiteDistribution",
            alias_configuration=cloudfront.AliasConfiguration(
                acm_cert_ref=certificate_arn, names=[domain_name],
            ),
            origin_configs=[
                cloudfront.SourceConfiguration(
                    s3_origin_source=cloudfront.S3OriginConfig(
                        s3_bucket_source=site_bucket, origin_access_identity=oai
                    ),
                    behaviors=[cloudfront.Behavior(is_default_behavior=True)],
                ),
            ],
        )

        # noinspection PyTypeChecker
        route53.ARecord(
            self,
            "SiteAliasRecord",
            record_name=domain_name,
            target=route53.AddressRecordTarget.from_alias(
                route53_targets.CloudFrontTarget(distribution)
            ),
            zone=hosted_zone,
        )

        s3_deployment.BucketDeployment(
            self,
            "DeployWithInvalidation",
            sources=[s3_deployment.Source.asset("assets/elm/dst")],
            destination_bucket=site_bucket,
            distribution=distribution,
            distribution_paths=["/*"],
        )
コード例 #27
0
    def __init__(self,
                 scope: Construct,
                 id: str,
                 *,
                 sources: str,
                 hosted_zone: HostedZone = None,
                 site_domain: str = None,
                 website_index: str = "index.html",
                 website_error: str = "error.html"):
        """
        This constructs creates:
            - S3 bucket
            - DNS Validated certificate
            - CloudFront web distribution
            - Route53 A record

        :param scope: The scope in which to define this construct.
        :param id: The scoped construct ID. Must be unique amongst siblings. If the ID includes a path separator (``/``), then it will be replaced by double dash ``--``.
        :param hosted_zone: A route53 hosted zone
        :param site_domain: The domain or subdomain you want to use for the website
        :param sources: A path to the location of the code
        :param website_index: Name of the index page, defaults to "index.html"
        :param website_error: Name of the error page, defaults to "error.html"
        """
        super().__init__(scope, id)

        # Construct code goes here
        if site_domain:
            CfnOutput(self, "Site", value=f"https://{site_domain}")

        # Content bucket
        self.site_bucket = aws_s3.Bucket(self,
                                         "SiteBucket",
                                         bucket_name=site_domain,
                                         website_index_document=website_index,
                                         website_error_document=website_error,
                                         public_read_access=True,
                                         removal_policy=RemovalPolicy.DESTROY)
        CfnOutput(self, "BucketArn", value=self.site_bucket.bucket_arn)
        CfnOutput(self,
                  "BucketWebsiteUrl",
                  value=self.site_bucket.bucket_website_url)
        CfnOutput(self,
                  "BucketWebsiteDomainName",
                  value=self.site_bucket.bucket_website_domain_name)

        # Certificate
        alias_config = None
        if hosted_zone:
            self.cert = DnsValidatedCertificate(self,
                                                f"{id}-bucket",
                                                domain_name=site_domain,
                                                hosted_zone=hosted_zone)
            CfnOutput(self, 'CertificateArn', value=self.cert.certificate_arn)
            alias_config = AliasConfiguration(
                acm_cert_ref=self.cert.certificate_arn,
                names=[site_domain],
                ssl_method=aws_cloudfront.SSLMethod.SNI,
                security_policy=aws_cloudfront.SecurityPolicyProtocol.
                TLS_V1_1_2016,
            )

        self.distr = CloudFrontWebDistribution(
            self,
            "SiteDistribution",
            alias_configuration=alias_config,
            origin_configs=[
                SourceConfiguration(
                    s3_origin_source=aws_cloudfront.S3OriginConfig(
                        s3_bucket_source=self.site_bucket),
                    behaviors=[
                        aws_cloudfront.Behavior(is_default_behavior=True)
                    ])
            ])

        CfnOutput(self, "DistributionId", value=self.distr.distribution_id)

        # Route 53 alias record for the cloudfront distribution
        if hosted_zone:
            aws_route53.ARecord(
                self,
                "SiteAliasRecord",
                zone=hosted_zone,
                target=aws_route53.AddressRecordTarget.from_alias(
                    aws_route53_targets.CloudFrontTarget(self.distr)),
                record_name=site_domain)

        aws_s3_deployment.BucketDeployment(
            self,
            "DeployWithInvalidation",
            sources=[aws_s3_deployment.Source.asset(sources)],
            destination_bucket=self.site_bucket,
            distribution=self.distr,
            distribution_paths=["/*"])
コード例 #28
0
    def __init__(self, scope: core.Construct, id: str, environment: str,
                 domain: str, **kwargs) -> None:
        """
        StaticSiteStack creates the CloudFormation Stack that creates the resources necessary to host a static web site from an S3 Bucket with a CloudFormation CDN and a custom domain name.  Three separate stacks are created based on the environment variable ('dev', 'stg', 'prod')

        arguments:
        environment -- Deployment Environment, e.g. one of ('dev', 'stg', 'prod')
        domain -- custom domain name owned by user, e.g. my-domain.com
        """

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

        # In the GitHub Actions Workflow, the Certificate is created using the CertificateStack and its arn is set as an environment variable
        self.certificate_arn = self.node.try_get_context("certificate_arn")

        bucket = s3.Bucket(self,
                           f"{environment}bucket",
                           website_index_document="index.html",
                           removal_policy=core.RemovalPolicy.DESTROY,
                           block_public_access=s3.BlockPublicAccess.BLOCK_ALL)

        core.CfnOutput(self, "sitebucketname", value=bucket.bucket_name)

        oai = cf.OriginAccessIdentity(
            self,
            f"OriginIdentity-{environment}-{domain}",
        )

        alias_configuration = cf.AliasConfiguration(
            acm_cert_ref=self.certificate_arn,
            names=[f"{environment}.{domain}"],
            ssl_method=cf.SSLMethod.SNI,
            security_policy=cf.SecurityPolicyProtocol.TLS_V1_1_2016)

        # Config dictionary for CloudFront distributions, no caching takes place in dev
        # The assumption is that it will be changed frequently and those changes will be tested
        # To use alternative sub-domains, change the keys of this dictionary to match the sub-domains used in certificate_stack.py
        cf_behavior_dict = {
            "dev":
            cf.Behavior(is_default_behavior=True,
                        min_ttl=core.Duration.seconds(0),
                        max_ttl=core.Duration.seconds(0),
                        default_ttl=core.Duration.seconds(0)),
            "stg":
            cf.Behavior(is_default_behavior=True),
            "prod":
            cf.Behavior(is_default_behavior=True)
        }

        source_config = cf.SourceConfiguration(
            s3_origin_source=cf.S3OriginConfig(s3_bucket_source=bucket,
                                               origin_access_identity=oai),
            behaviors=[cf_behavior_dict[environment]])

        cf_dist = cf.CloudFrontWebDistribution(
            self,
            f"{environment}-static-site-distribution",
            alias_configuration=alias_configuration,
            origin_configs=[source_config],
            viewer_protocol_policy=cf.ViewerProtocolPolicy.REDIRECT_TO_HTTPS)

        core.CfnOutput(self, "distid", value=cf_dist.distribution_id)

        # Route53 alias record for the CloudFront Distribution
        hosted_zone = route53.HostedZone.from_lookup(
            self, "static-site-hosted-zone-id", domain_name=domain)

        route53.ARecord(self,
                        'static-site-alias-record',
                        record_name=f"{environment}.{domain}",
                        target=route53.AddressRecordTarget.from_alias(
                            targets.CloudFrontTarget(cf_dist)),
                        zone=hosted_zone)
コード例 #29
0
def add_static_site(stack: CDKMasterStack, domain: str, bucket_name: str, prefix: str = ""):

    # Construct code goes here
    core.CfnOutput(stack, f"{prefix}Site", value=f"https://{domain}")

    # Content bucket
    kix.info("Bucket Name: " + bucket_name)
    site_bucket = aws_s3.Bucket(
        stack, f"{prefix}SiteBucket",
        bucket_name=bucket_name,
        website_index_document="index.html",
        website_error_document="index.html",
        public_read_access=True,
        removal_policy=core.RemovalPolicy.DESTROY)
    core.CfnOutput(stack, f"{prefix}BucketArn", value=site_bucket.bucket_arn)

    # Certificate
    kix.info("Creating Certificate")
    cert = aws_certificatemanager.DnsValidatedCertificate(
        stack, f"{prefix}ValidatedCert",
        domain_name=domain,
        hosted_zone=stack.zone)
    core.CfnOutput(stack, f"{prefix}CertificateArn", value=cert.certificate_arn)

    kix.info("Creating Distribution")
    distribution = aws_cloudfront.CloudFrontWebDistribution(
        stack, f"{prefix}SiteDistribution",
        alias_configuration=aws_cloudfront.AliasConfiguration(
            acm_cert_ref=cert.certificate_arn,
            names=[domain],
            ssl_method=aws_cloudfront.SSLMethod.SNI,
            security_policy=aws_cloudfront.SecurityPolicyProtocol.TLS_V1_1_2016,
        ),
        origin_configs=[
            aws_cloudfront.SourceConfiguration(
                s3_origin_source=aws_cloudfront.S3OriginConfig(s3_bucket_source=site_bucket),
                behaviors=[aws_cloudfront.Behavior(is_default_behavior=True)]
            )],
        error_configurations=[
            aws_cloudfront.CfnDistribution.CustomErrorResponseProperty(
                error_code=403,
                response_code=200,
                response_page_path="/index.html"
            ),
            aws_cloudfront.CfnDistribution.CustomErrorResponseProperty(
                error_code=404,
                response_code=200,
                response_page_path="/index.html"
            )
        ]
    )
    core.CfnOutput(stack, f"{prefix}DistributionId", value=distribution.distribution_id)
    a_record_target = aws_route53.AddressRecordTarget.from_alias(aws_route53_targets.CloudFrontTarget(distribution))

    # Route 53 alias record for the CloudFront distribution
    kix.info("Routing A-Record Alias")
    aws_route53.ARecord(
        stack, f"{prefix}SiteAliasRecord",
        zone=stack.zone,
        target=a_record_target,
        record_name=domain)
コード例 #30
0
    def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)
        # super().__init__(scope, id, context, outdir)

        print()
        # Common Stack Tags
        for k, v in constants.COMMON_TAGS.items():
            core.Tag.add(self, key=k, value=v)

        # Hosted Zone
        if constants.HOSTED_ZONE["id"]:
            hosted_zone = aws_route53.HostedZone.from_hosted_zone_attributes(
                self,
                "ImportedHostedZone",
                hosted_zone_id=constants.HOSTED_ZONE["id"],
                zone_name=constants.HOSTED_ZONE["name"])
        else:
            hosted_zone = aws_route53.HostedZone(
                self,
                "MainHostedZone",
                zone_name=constants.HOSTED_ZONE["name"],
                comment="Hosted Zone for {}".format(
                    constants.HOSTED_ZONE["name"]),
            )

        # ACM Certificate
        if constants.CERTIFICATE["arn"]:
            acm_certificate = aws_certificatemanager.Certificate.from_certificate_arn(
                self,
                "ImportedCertificate",
                certificate_arn=constants.CERTIFICATE["arn"])
        else:
            acm_certificate = aws_certificatemanager.DnsValidatedCertificate(
                self,
                "CloudFrontCertificate",
                hosted_zone=hosted_zone,
                region=constants.CERTIFICATE["region"],
                domain_name=constants.HOSTED_ZONE["domain"],
                subject_alternative_names=constants.CERTIFICATE["alt_domains"],
                validation_method=aws_certificatemanager.ValidationMethod.DNS)
            acm_certificate.node.add_dependency(hosted_zone)

        # Website Bucket
        website_bucket = aws_s3.Bucket(
            self,
            "WebsiteBucket",
            encryption=aws_s3.BucketEncryption.S3_MANAGED,
            removal_policy=core.RemovalPolicy.DESTROY)

        # Cloudfront Origin Access Identity (OAI)
        website_bucket_oai = aws_cloudfront.CfnCloudFrontOriginAccessIdentity(
            self,
            "CloudfrontOAI",
            cloud_front_origin_access_identity_config=aws_cloudfront.
            CfnCloudFrontOriginAccessIdentity.
            CloudFrontOriginAccessIdentityConfigProperty(
                comment="CloudFrontOAIFor{}".format(
                    constants.PROJECT_CODE.capitalize())))

        # Canonical User Principal of OAI
        oai_canonical_user_principal = aws_iam.CanonicalUserPrincipal(
            website_bucket_oai.attr_s3_canonical_user_id)

        # Website Bucket Policy
        website_bucket.add_to_resource_policy(
            aws_iam.PolicyStatement(
                actions=["s3:GetObject"],
                resources=[website_bucket.arn_for_objects("*")],
                principals=[oai_canonical_user_principal],
                effect=aws_iam.Effect.ALLOW))

        # Adopt Lambda Function
        lambda_function = aws_lambda.Function.from_function_arn(
            self,
            "UrlRewriteFunction",
            function_arn=constants.URL_REWRITE_FUNCTION_ARN)

        lambda_function_version_arn = aws_lambda.Version.from_version_arn(
            self,
            "LambdaFunctionArn",
            version_arn=constants.URL_REWRITE_FUNCTION_VERSION_ARN)

        # CloudFront Web Distribution
        cloudfront_distribution = aws_cloudfront.CloudFrontWebDistribution(
            self,
            "CloudFrontDistribution",
            comment="waqqas.tech",
            default_root_object="index.html",
            viewer_protocol_policy=aws_cloudfront.ViewerProtocolPolicy.
            REDIRECT_TO_HTTPS,
            alias_configuration=aws_cloudfront.AliasConfiguration(
                acm_cert_ref=acm_certificate.certificate_arn,
                security_policy=aws_cloudfront.SecurityPolicyProtocol.
                TLS_V1_2_2018,
                names=constants.CLOUDFRONT["alt_domains"]),
            origin_configs=[
                aws_cloudfront.SourceConfiguration(
                    s3_origin_source=aws_cloudfront.S3OriginConfig(
                        s3_bucket_source=website_bucket,
                        origin_access_identity_id=website_bucket_oai.ref),
                    behaviors=[
                        aws_cloudfront.Behavior(
                            allowed_methods=aws_cloudfront.
                            CloudFrontAllowedMethods.GET_HEAD_OPTIONS,
                            cached_methods=aws_cloudfront.
                            CloudFrontAllowedCachedMethods.GET_HEAD,
                            compress=True,
                            is_default_behavior=True,
                            path_pattern="*",
                            default_ttl=core.Duration.seconds(
                                amount=constants.CLOUDFRONT['default_ttl']),
                            lambda_function_associations=[
                                aws_cloudfront.LambdaFunctionAssociation(
                                    event_type=aws_cloudfront.
                                    LambdaEdgeEventType.ORIGIN_REQUEST,
                                    lambda_function=lambda_function_version_arn
                                )
                            ])
                    ])
            ])

        # CloudFront Route53 Record
        primary_dns_record = aws_route53.ARecord(
            self,
            "PrimaryDNSRecord",
            zone=hosted_zone,
            comment="{} CloudFront Dist Alias Record".format(
                constants.PROJECT_CODE),
            record_name="{}.".format(constants.HOSTED_ZONE["domain"]),
            target=aws_route53.RecordTarget.from_alias(
                aws_route53_targets.CloudFrontTarget(cloudfront_distribution)),
            ttl=core.Duration.seconds(
                amount=constants.CLOUDFRONT["default_ttl"]),
        )

        # Artifact Bucket
        artifact_bucket = aws_s3.Bucket(
            self,
            "ArtifactBucket",
            encryption=aws_s3.BucketEncryption.S3_MANAGED,
            removal_policy=core.RemovalPolicy.DESTROY)

        # CodeBuild
        codebuild_environment_variables = aws_codebuild.BuildEnvironmentVariable(
            value=website_bucket.bucket_name)
        codebuild_environment = aws_codebuild.BuildEnvironment(
            build_image=aws_codebuild.LinuxBuildImage.
            UBUNTU_14_04_PYTHON_3_7_1,
            compute_type=aws_codebuild.ComputeType.SMALL)
        codebuild_buildspec = aws_codebuild.BuildSpec.from_object(
            value=buildspec.BUILDSPEC)
        codebuild_project = aws_codebuild.PipelineProject(
            self,
            "CodeBuildProject",
            environment_variables={
                "BUCKET_NAME": codebuild_environment_variables
            },
            environment=codebuild_environment,
            build_spec=codebuild_buildspec,
            description="CodeBuild Project for {} Content".format(
                constants.PROJECT_CODE),
            timeout=core.Duration.seconds(amount=300))
        # TODO: Lock down permissions for buckets
        codebuild_project.add_to_role_policy(
            aws_iam.PolicyStatement(actions=["s3:*"],
                                    effect=aws_iam.Effect.ALLOW,
                                    resources=[
                                        website_bucket.arn_for_objects("*"),
                                        artifact_bucket.arn_for_objects("*"),
                                        website_bucket.bucket_arn,
                                        artifact_bucket.bucket_arn,
                                    ]))
        # Codepipeline
        codepipeline = aws_codepipeline.Pipeline(
            self,
            "CodePipelineWebsiteContent",
            artifact_bucket=artifact_bucket,
            stages=[
                aws_codepipeline.StageProps(
                    stage_name="Source",
                    actions=[
                        aws_codepipeline_actions.GitHubSourceAction(
                            oauth_token=core.SecretValue(
                                value=constants.GITHUB_OAUTH_TOKEN),
                            output=aws_codepipeline.Artifact(
                                artifact_name="source"),
                            owner=constants.GITHUB_USER_NAME,
                            repo=constants.GITHUB_REPO_NAME,
                            branch=constants.BRANCH_NAME,
                            action_name="GithubSource",
                            trigger=aws_codepipeline_actions.GitHubTrigger.
                            WEBHOOK)
                    ]),
                aws_codepipeline.StageProps(
                    stage_name="Build",
                    actions=[
                        aws_codepipeline_actions.CodeBuildAction(
                            input=aws_codepipeline.Artifact(
                                artifact_name="source"),
                            project=codebuild_project,
                            type=aws_codepipeline_actions.CodeBuildActionType.
                            BUILD,
                            action_name="HugoBuild")
                    ])
            ])
        # TODO: Lock down permissions for buckets
        codepipeline.add_to_role_policy(
            aws_iam.PolicyStatement(actions=["s3:*"],
                                    effect=aws_iam.Effect.ALLOW,
                                    resources=[
                                        website_bucket.arn_for_objects("*"),
                                        artifact_bucket.arn_for_objects("*"),
                                        website_bucket.bucket_arn,
                                        artifact_bucket.bucket_arn,
                                    ]))