示例#1
0
 def create_alias(self, scope: Construct, subdomain_name):
     ARecord(
         scope,
         f"{subdomain_name}ARecord",
         target=RecordTarget.from_alias(DomainAlias(self.subdomain_name)),
         zone=dns.get_hosted_zone(),
         record_name=dns.subdomain_to_fqdn(subdomain_name),
     )
     AaaaRecord(
         scope,
         f"{subdomain_name}AAAARecord",
         target=RecordTarget.from_alias(DomainAlias(self.subdomain_name)),
         zone=dns.get_hosted_zone(),
         record_name=dns.subdomain_to_fqdn(subdomain_name),
     )
    def create_route53(stack, domain, distrubution):
        hosted_zone = HostedZone.from_lookup(
            stack,
            'RadiantLoungeZone',
            domain_name=domain
        )

        ARecord(
            stack,
            f'RadiantLoungeARecord',
            zone=hosted_zone,
            target=RecordTarget.from_alias(CloudFrontTarget(distrubution))
        )

        AaaaRecord(
            stack,
            f'RadiantLoungeAaaaRecord',
            zone=hosted_zone,
            target=RecordTarget.from_alias(CloudFrontTarget(distrubution))
        )
示例#3
0
    def __init__(self, scope: Construct, id: str, *, fqdn: str,
                 target) -> None:
        super().__init__(scope, id)

        hosted_zone_name = dns.get_hosted_zone_name()
        if not fqdn.endswith(hosted_zone_name):
            raise Exception(f"FQDN {fqdn} not within {hosted_zone_name}")
        record_name = fqdn[0:-len(hosted_zone_name) - 1]

        route53.ARecord(
            self,
            id,
            target=RecordTarget.from_alias(target),
            zone=dns.get_hosted_zone(),
            record_name=record_name,
        )
示例#4
0
    def __init__(self, scope: core.Construct, construct_id: str, cert_arn: str,
                 hosted_zone_id: str, domain_name: str, **kwargs) -> None:
        """
        :param cert_arn: ARN of certificate to use
        :param hosted_zone_id: ID of hosted zone to use
        :param domain_name: Domain name to use
        """
        super().__init__(scope, construct_id, **kwargs)

        ##################################
        # WEBSITE HOSTING INFRASTRUCTURE #
        ##################################

        # Grab hosted zone for the website to contain our records and an SSL certificate for HTTPS. These two have to
        # be grabbed from existing resources instead of created here because CloudFormation will time out waiting for a
        # newly-created cert to validate.
        self.hosted_zone = PublicHostedZone.from_public_hosted_zone_id(
            self, "personal-site-hosted-zone", hosted_zone_id)
        self.cert = Certificate.from_certificate_arn(self,
                                                     "personal-site-cert",
                                                     cert_arn)

        # Add an S3 bucket to host the website content
        self.website_bucket = Bucket(self,
                                     "personal-site-bucket",
                                     bucket_name=domain_name,
                                     removal_policy=RemovalPolicy.DESTROY,
                                     public_read_access=True,
                                     website_index_document="index.html",
                                     website_error_document="index.html")

        # Create a cloudfront distribution for the site
        self.distribution = Distribution(
            self,
            "personal-site-cf-distribution",
            default_behavior={
                "origin": S3Origin(self.website_bucket),
                "allowed_methods": AllowedMethods.ALLOW_GET_HEAD_OPTIONS,
                "viewer_protocol_policy":
                ViewerProtocolPolicy.REDIRECT_TO_HTTPS
            },
            certificate=self.cert,
            minimum_protocol_version=SecurityPolicyProtocol.TLS_V1_2_2019,
            enable_ipv6=True,
            domain_names=[domain_name, f"www.{domain_name}"])

        # Point traffic to base and www.base to the cloudfront distribution, for both IPv4 and IPv6
        ARecord(self,
                "personal-site-a-record",
                zone=self.hosted_zone,
                record_name=f"{domain_name}.",
                target=RecordTarget.from_alias(
                    CloudFrontTarget(self.distribution)))
        ARecord(self,
                "personal-site-a-record-www",
                zone=self.hosted_zone,
                target=RecordTarget.from_alias(
                    CloudFrontTarget(self.distribution)),
                record_name=f"www.{domain_name}.")
        AaaaRecord(self,
                   "personal-site-aaaa-record",
                   zone=self.hosted_zone,
                   record_name=f"{domain_name}.",
                   target=RecordTarget.from_alias(
                       CloudFrontTarget(self.distribution)))
        AaaaRecord(self,
                   "personal-site-aaaa-record-www",
                   zone=self.hosted_zone,
                   target=RecordTarget.from_alias(
                       CloudFrontTarget(self.distribution)),
                   record_name=f"www.{domain_name}.")

        #############################
        # WEBSITE CD INFRASTRUCTURE #
        #############################

        # CodeBuild project to build the website
        self.code_build_project = \
            Project(self, "personal-site-builder",
                    project_name="PersonalWebsite",
                    description="Builds & deploys a personal static website on changes from GitHub",
                    source=Source.git_hub(
                        owner="c7c8",
                        repo="crmyers.dev",
                        clone_depth=1,
                        branch_or_ref="master",
                        webhook_filters=[
                            FilterGroup.in_event_of(EventAction.PUSH, EventAction.PULL_REQUEST_MERGED).and_branch_is(
                                "master")]),
                    artifacts=Artifacts.s3(bucket=self.website_bucket, include_build_id=False,
                                           package_zip=False,
                                           path="/"),
                    build_spec=BuildSpec.from_object_to_yaml({
                        "version": "0.2",
                        "phases": {
                            "install": {
                                "runtime-versions": {
                                    "nodejs": 10,
                                }
                            },
                            "pre_build": {
                                "commands": ["npm install"]
                            },
                            "build": {
                                "commands": [
                                    "npm run-script build &&",
                                    f"aws cloudfront create-invalidation --distribution-id={self.distribution.distribution_id} --paths '/*'"
                                ]
                            }
                        },
                        "artifacts": {
                            "files": ["./*"],
                            "name": ".",
                            "discard-paths": "no",
                            "base-directory": "dist/crmyers-dev"
                        }
                    }))
        self.code_build_project.role.add_to_policy(
            PolicyStatement(
                effect=Effect.ALLOW,
                resources=[
                    f"arn:aws:cloudfront::{self.account}:distribution/{self.distribution.distribution_id}"
                ],
                actions=['cloudfront:CreateInvalidation']))

        # Set up an SNS topic for text message notifications
        self.deployment_topic = Topic(self,
                                      'personal-site-deployment-topic',
                                      topic_name='WebsiteDeployments',
                                      display_name='Website Deployments')
        self.deployment_topic.add_subscription(SmsSubscription("+19255968684"))
        self.code_build_project.on_build_failed(
            "BuildFailed",
            target=targets.SnsTopic(self.deployment_topic,
                                    message=RuleTargetInput.from_text(
                                        "Build for crmyers.dev FAILED")))
        self.code_build_project.on_build_succeeded(
            "BuildSucceeded",
            target=targets.SnsTopic(self.deployment_topic,
                                    message=RuleTargetInput.from_text(
                                        "Build for crmyers.dev SUCCEEDED")))
示例#5
0
    def __init__(self, app: App, id: str, env: Environment) -> None:
        super().__init__(app, id, env=env)

        # start by getting the DNS zone we're going to work with
        zone = HostedZone.from_lookup(self, "Dominick", domain_name=DOMAIN)

        # create a certificate for the web service which matches its hostname
        cert = Certificate(self,
                           "Cletus",
                           domain_name=HOSTNAME,
                           validation=CertificateValidation.from_dns(zone))

        # the services will live in a vpc, of course
        vpc = ec2.Vpc(self, "Virgil")

        # we're going to scale this web-service automatically
        asg = AutoScalingGroup(
            self,
            "Alice",
            vpc=vpc,
            user_data=http_service(),
            instance_type=ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE2,
                                              ec2.InstanceSize.MICRO),
            machine_image=ec2.AmazonLinuxImage(
                generation=ec2.AmazonLinuxGeneration.AMAZON_LINUX_2))

        # explicitly allow internal access from the vpc just to be safe
        asg.connections.allow_internally(Port.tcp(WEB_PORT), "web-service")
        asg.connections.allow_internally(Port.tcp(NOT_WEB), "not-web")

        # expose the scaling group ports and permit egress
        asg.connections.allow_from_any_ipv4(Port.tcp(WEB_PORT))
        asg.connections.allow_from_any_ipv4(Port.tcp(NOT_WEB))

        # create a health check for the not-web service that currently
        if NOT_WEB_HEALTH_CHECKS:
            # points to the not-web service
            checker = HealthCheck(interval=Duration.seconds(10),
                                  port=NOT_WEB,
                                  protocol=Protocol.TCP)
        else:
            # points to the web port where our demo server listens
            checker = HealthCheck(interval=Duration.seconds(10),
                                  port=str(WEB_PORT),
                                  protocol=WEB_PROT)

        # put the scaling group behind a network target group for the LB
        notwebish = NetworkTargetGroup(self,
                                       "Allison",
                                       vpc=vpc,
                                       health_check=checker,
                                       targets=[asg],
                                       port=NOT_WEB,
                                       protocol=Protocol.TCP)

        # for the web-like ports, we can use the default health check
        webish = NetworkTargetGroup(
            self,
            "Alicen",
            vpc=vpc,
            health_check=HealthCheck(interval=Duration.seconds(10)),
            targets=[asg],
            port=WEB_PORT,
            protocol=WEB_PROT)

        if True:
            # create the load balancer and put it into dns
            lb = NetworkLoadBalancer(self,
                                     "Lisa",
                                     vpc=vpc,
                                     internet_facing=True)

            # create a hostname for the service
            CnameRecord(self,
                        "Carl",
                        domain_name=lb.load_balancer_dns_name,
                        zone=zone,
                        record_name=HOSTNAME.split('.')[0],
                        ttl=Duration.seconds(60))
        else:
            # a multi-step deployment could allow using an alias in R53
            lb = NetworkLoadBalancer.from_network_load_balancer_attributes(
                self,
                "Larry",
                vpc=vpc,
                load_balancer_arn=some.load_balancer_arn,
                load_balancer_dns_name=HOSTNAME,
                load_balancer_canonical_hosted_zone_id=zone.hosted_zone_id)

            # create a hostname for the service
            AaaaRecord(self,
                       "Eric",
                       zone=zone,
                       record_name=HOSTNAME.split('.')[0],
                       target=RecordTarget.from_alias(LoadBalancerTarget(lb)))

        # point the load balancer to the target group for the ssl service
        #
        # TODO: determine if we need to use the same cert for pub-facing
        #       and internal service
        listener_cert = ListenerCertificate(cert.certificate_arn)
        lb.add_listener("Cecil",
                        port=443,
                        certificates=[listener_cert],
                        default_target_groups=[webish])

        # point the load balancer to the target group for the web service
        lb.add_listener("Webster", port=80, default_target_groups=[webish])

        # point the load balancer to the group for the not-web service
        lb.add_listener("NotWeb",
                        default_target_groups=[notwebish],
                        port=NOT_WEB,
                        protocol=Protocol.TCP)

        # auto scale the, uh, autoscaling group
        asg.scale_on_cpu_utilization("ScaleCPU", target_utilization_percent=80)

        # emit some output values, largely for console use
        CfnOutput(self,
                  "LB",
                  export_name="LB",
                  value=lb.load_balancer_dns_name)
        CfnOutput(self,
                  "HTTP",
                  export_name="HTTP",
                  value="http://{}/".format(HOSTNAME))
        CfnOutput(self,
                  "HTTPS",
                  export_name="HTTPS",
                  value="https://{}/".format(HOSTNAME))
        CfnOutput(self,
                  "TCP",
                  export_name="TCP",
                  value="tcp://{}:{}/".format(HOSTNAME, NOT_WEB))
        CfnOutput(self, "Cert", export_name="Cert", value=cert.certificate_arn)
示例#6
0
    def __init__(self, scope: Construct, id: str, *, deployment: Deployment, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        Tags.of(self).add("Application", self.application_name)
        Tags.of(self).add("Deployment", deployment.value)

        hosted_zone = HostedZone.from_lookup(
            self,
            "Zone",
            domain_name="openttd.com",
        )
        fqdn = "www.openttd.com"

        certificate = DnsValidatedCertificate(
            self,
            "OpenttdCom-Certificate",
            hosted_zone=hosted_zone,
            domain_name=fqdn,
            subject_alternative_names=["*.openttd.com", "openttd.com"],
            region="us-east-1",
            validation_method=ValidationMethod.DNS,
        )

        func = lambda_edge.create_function(
            self,
            "OpenttdComRedirect",
            runtime=Runtime.NODEJS_10_X,
            handler="index.handler",
            code=Code.from_asset("./lambdas/openttd-com-redirect"),
        )

        s3_cloud_front = S3CloudFront(
            self,
            "S3CloudFront",
            subdomain_name=fqdn,
            cert=CertificateResult(certificate, certificate.certificate_arn, fqdn),
            additional_fqdns=["*.openttd.com", "openttd.com"],
            lambda_function_associations=[
                LambdaFunctionAssociation(
                    event_type=LambdaEdgeEventType.ORIGIN_REQUEST,
                    lambda_function=func,
                ),
            ],
            no_dns=True,
        )

        S3CloudFrontPolicy(
            self,
            "S3cloudFrontPolicy",
            s3_cloud_front=s3_cloud_front,
        )

        for record_name in ("www", None):
            route53.ARecord(
                self,
                f"{record_name}.openttd.com-ARecord",
                target=RecordTarget.from_alias(CloudFrontTarget(s3_cloud_front.distribution)),
                zone=hosted_zone,
                record_name=record_name,
            )
            route53.AaaaRecord(
                self,
                f"{record_name}.openttd.com-AaaaRecord",
                target=RecordTarget.from_alias(CloudFrontTarget(s3_cloud_front.distribution)),
                zone=hosted_zone,
                record_name=record_name,
            )