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)) )
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, )
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")))
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)
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, )