Ejemplo n.º 1
0
def create_dnsrecords():
    return route53.RecordSetGroup(
        'dns',
        HostedZoneName=Sub('${domain}.'),
        RecordSets=[
            route53.RecordSet(
                'dnsInstance',
                Name=_subdomain_for_instance(),
                ResourceRecords=[GetAtt('devserver', 'PublicIp')],
                Type='A',
                TTL=300,
            ),
            route53.RecordSet(
                'dnsTlsApplication',
                Name=_subdomain_for_application(),
                Type='A',
                AliasTarget=route53.AliasTarget(
                    DNSName=GetAtt('tlsFrontend', 'DNSName'),
                    HostedZoneId=GetAtt('tlsFrontend',
                                        'CanonicalHostedZoneID'),
                ),
            ),
            route53.RecordSet(
                'dnsTlsJenkins',
                Name=_subdomain_for_jenkins(),
                Type='A',
                AliasTarget=route53.AliasTarget(
                    DNSName=GetAtt('tlsFrontend', 'DNSName'),
                    HostedZoneId=GetAtt('tlsFrontend',
                                        'CanonicalHostedZoneID'),
                ),
            ),
        ],
    )
Ejemplo n.º 2
0
    def handle(self, chain_context):
        template = chain_context.template

        template.add_resource(route53.RecordSetGroup(
            "Route53Records",
            RecordSets=[
                route53.RecordSet(
                    DNS_NAME % self.name,
                    Weight=1,
                    SetIdentifier="original",
                    AliasTarget=route53.AliasTarget(
                        HostedZoneId=self.hosted_zone_id,
                        DNSName=self.target,
                        EvaluateTargetHealth=False,
                    ),
                    Name=Join("", [
                        self.dns_name,
                        ".",
                        self.base_domain,
                        "."
                    ]),
                    Type="A",
                )
            ],
            HostedZoneName=Join("", [self.base_domain, "."])
        ))
Ejemplo n.º 3
0
    def resources(self, stack: Stack) -> list[AWSObject]:
        """Return list of AWSObject associated with the construct."""
        # Add bucket policy granting read access to te cloudfront distribution
        self.add_oai_access_to_bucket()

        result = [
            *self.bucket.resources(stack),
            self.cache_policy,
            self.distribution,
            self.origin_access_identity,
        ]

        # Add a lambda invalidating cloudfront cache when bucket objects are modified
        result.extend(self.add_cache_invalidation(stack))

        # Add route53 records if needed
        if self.r53_route_from:
            for zone_id, domain in self.r53_route_from:
                result.append(
                    route53.RecordSetType(
                        name_to_id(f"{self.name}-{domain}-r53-rset"),
                        AliasTarget=route53.AliasTarget(
                            DNSName=self.domain_name,
                            # Z2FDTNDATAQYW2 is always the hosted zone ID when you
                            # create an alias record that routes traffic to a
                            # CloudFront distribution
                            HostedZoneId="Z2FDTNDATAQYW2",
                        ),
                        Name=domain,
                        HostedZoneId=zone_id,
                        Type="A",
                    ))
        return result
Ejemplo n.º 4
0
    def create_r53_record(self, hosted_zone_name):
        """
        Function to create r53 recourdset to associate with ELB
        :param hosted_zone_name: R53 hosted zone to create record in
        """
        if self.elb_config.public_unit:
            name = Join('', [Ref('AWS::StackName'),
                             '-',
                             self.title,
                             '.',
                             hosted_zone_name])
        else:
            name = Join('', [self.title,
                             '.',
                             hosted_zone_name])
        self.elb_r53 = self.template.add_resource(route53.RecordSetGroup(
            self.title + 'R53',
            RecordSets=[route53.RecordSet(
                Name=name,
                AliasTarget=route53.AliasTarget(dnsname=GetAtt(self.trop_elb, 'DNSName'),
                                                hostedzoneid=GetAtt(self.trop_elb, 'CanonicalHostedZoneNameID')),
                Type='A')]))

        if not self.elb_config.public_unit:
            self.elb_r53.HostedZoneId = self.network_config.private_hosted_zone_id
        else:
            self.elb_r53.HostedZoneName = hosted_zone_name

        self.template.add_output(Output(
            self.trop_elb.title,
            Description='URL of the {0} ELB'.format(self.title),
            Value=Join('', ['http://', self.elb_r53.RecordSets[0].Name])
        ))
    def route53_record_set(self):
        t = self.template
        LocalDNS = t.add_resource(
            route53.RecordSetGroup(
                "LocalDNS",
                HostedZoneName=self.vars["HostedZoneDomainName"] + ".",
                RecordSets=[
                    route53.RecordSet(
                        Name=self.vars["FQDNInternal"] + ".",
                        Type="A",
                        AliasTarget=route53.AliasTarget(
                            HostedZoneId=CLOUDFRONT_HOSTEDZONEID,
                            DNSName=GetAtt(self.SiteCFDistribution,
                                           "DomainName"),
                        ),
                    )
                ],
            ))

        LocalDNS = t.add_output(
            Output(
                "LocalDNS",
                Description="Internal DNS domainname set in route53",
                Value=self.vars["FQDNInternal"],
            ))
Ejemplo n.º 6
0
 def entry(hostname, i):
     if _is_domain_2nd_level(hostname):
         # must be an alias as it is a 2nd-level domain like elifesciences.net
         hostedzone = hostname + "."
         ensure(context['elb'],
                "2nd-level domains aliases are only supported for ELBs")
         return route53.RecordSetType(R53_CNAME_TITLE % (i + 1),
                                      HostedZoneName=hostedzone,
                                      Name=hostname,
                                      Type="A",
                                      AliasTarget=route53.AliasTarget(
                                          GetAtt(
                                              ELB_TITLE,
                                              "CanonicalHostedZoneNameID"),
                                          GetAtt(ELB_TITLE, "DNSName")))
     else:
         hostedzone = context['domain'] + "."
         return route53.RecordSetType(
             R53_CNAME_TITLE % (i + 1),
             HostedZoneName=hostedzone,
             Name=hostname,
             Type="CNAME",
             TTL="60",
             ResourceRecords=[context['full_hostname']],
         )
Ejemplo n.º 7
0
    def handle(self, chain_context):
        template = chain_context.template

        name = 'AlbAlias%s' % chain_context.instance_name

        template.add_resource(
            route53.RecordSetGroup(
                "Route53Records",
                RecordSets=[
                    route53.RecordSet(
                        name,
                        Weight=1,
                        SetIdentifier="original",
                        AliasTarget=route53.AliasTarget(
                            HostedZoneId=self.hosted_zone_id,
                            DNSName=self.dns_name,
                            EvaluateTargetHealth=False,
                        ),
                        Name=Join("", [
                            Ref("namespace"), "-",
                            Ref("env"), ".", self.base_domain, "."
                        ]),
                        Type="A",
                    )
                ],
                HostedZoneName=Join("", [self.base_domain, "."])))
Ejemplo n.º 8
0
 def __init__(self, title, name, domain_name, zoneid_name, **kwargs):
     super().__init__(title, **kwargs)
     self.AliasTarget = r53.AliasTarget(DNSName=GetAtt(name, domain_name),
                                        HostedZoneId=GetAtt(
                                            name, zoneid_name))
     self.Name = Ref(name)
     self.Type = 'A'
Ejemplo n.º 9
0
    def declare_domain(self, domain_name: str, hosted_zone_id: str,
                       stage_name: str) -> list[AWSObject]:
        """Declare a custom domain for one of the API stage.

        Note that when a custom domain is created then a certificate is automatically
        created for that domain.

        :param domain_name: domain name
        :param hosted_zone_id: hosted zone in which the domain belongs to
        :param stage_name: stage that should be associated with that domain
        :return: a list of AWSObject
        """
        result = []
        certificate_id = name_to_id(self.name + domain_name + "Certificate")
        certificate = Certificate(
            certificate_id,
            DomainName=domain_name,
            DomainValidationOptions=[
                DomainValidationOption(DomainName=domain_name,
                                       HostedZoneId=hosted_zone_id)
            ],
            ValidationMethod="DNS",
        )
        result.append(certificate)
        domain = apigatewayv2.DomainName(
            name_to_id(self.name + domain_name + "Domain"),
            DomainName=domain_name,
            DomainNameConfigurations=[
                apigatewayv2.DomainNameConfiguration(
                    CertificateArn=certificate.ref())
            ],
        )
        result.append(domain)
        result.append(
            apigatewayv2.ApiMapping(
                name_to_id(self.name + domain_name + "ApiMapping"),
                DomainName=domain.ref(),
                ApiId=self.ref,
                Stage=self.stage_ref(stage_name),
            ))
        result.append(
            route53.RecordSetType(
                name_to_id(self.name + domain_name + "DNS"),
                Name=domain_name,
                Type="A",
                HostedZoneId=hosted_zone_id,
                AliasTarget=route53.AliasTarget(
                    DNSName=GetAtt(
                        name_to_id(self.name + domain_name + "Domain"),
                        "RegionalDomainName",
                    ),
                    HostedZoneId=GetAtt(
                        name_to_id(self.name + domain_name + "Domain"),
                        "RegionalHostedZoneId",
                    ),
                    EvaluateTargetHealth=False,
                ),
            ))
        return result
Ejemplo n.º 10
0
 def __init__(self, title, **kwargs):
     super().__init__(title, **kwargs)
     self.Condition = 'RecordSetCloudFront'
     self.AliasTarget = r53.AliasTarget(DNSName=GetAtt(
         'CloudFrontDistribution', 'DomainName'),
                                        HostedZoneId=cfg.HostedZoneIdCF)
     self.Name = Sub('${EnvRole}${RecordSetCloudFrontSuffix}.cdn.%s' %
                     cfg.HostedZoneNameEnv)
     self.Type = 'A'
Ejemplo n.º 11
0
    def create_dns_records(self, tile_server_lb):
        self.add_condition('BlueCondition', Equals('Blue', Ref(self.color)))
        self.add_condition('GreenCondition', Equals('Green', Ref(self.color)))

        self.add_resource(r53.RecordSetGroup(
            'dnsPublicRecordsBlue',
            Condition='BlueCondition',
            HostedZoneName=Join('', [Ref(self.public_hosted_zone_name), '.']),
            RecordSets=[
                r53.RecordSet(
                    'dnsTileServersBlue',
                    AliasTarget=r53.AliasTarget(
                        GetAtt(tile_server_lb, 'CanonicalHostedZoneNameID'),
                        GetAtt(tile_server_lb, 'DNSName'),
                        True
                    ),
                    Name=Join('', ['blue-tiles.',
                                   Ref(self.public_hosted_zone_name), '.']),
                    Type='A'
                )
            ]
        ))

        self.add_resource(r53.RecordSetGroup(
            'dnsPublicRecordsGreen',
            Condition='GreenCondition',
            HostedZoneName=Join('', [Ref(self.public_hosted_zone_name), '.']),
            RecordSets=[
                r53.RecordSet(
                    'dnsTileServersGreen',
                    AliasTarget=r53.AliasTarget(
                        GetAtt(tile_server_lb, 'CanonicalHostedZoneNameID'),
                        GetAtt(tile_server_lb, 'DNSName'),
                        True
                    ),
                    Name=Join('', ['green-tiles.',
                                   Ref(self.public_hosted_zone_name), '.']),
                    Type='A'
                )
            ]
        ))
Ejemplo n.º 12
0
    def add_to_template(self, t):

        dns_param = ensure_param(t, self.value.output_dns(), 'String')
        zone_id = "Z2FDTNDATAQYW2"
        r = route53.RecordSet(
            '{}CFRecord'.format(self._safe_dns_name(self.name)),
            Name="{}{}.".format(self.name, self.stack.domain_name),
            Type="A",
            AliasTarget=route53.AliasTarget(HostedZoneId=zone_id,
                                            DNSName=Ref(dns_param)))

        return r
Ejemplo n.º 13
0
 def add_route53(self, stack_name, template, provision_refs):
     template.add_resource(
         route53.RecordSetType(
             "NetworkDNSRecord",
             HostedZoneName="network.shipchain.io.",
             Comment=f"DNS name for {stack_name} network ALB",
             Name=f"{stack_name}.network.shipchain.io.",
             Type="A",
             AliasTarget=route53.AliasTarget(
                 DNSName=GetAtt(provision_refs.alb, 'DNSName'),
                 HostedZoneId=GetAtt(provision_refs.alb,
                                     "CanonicalHostedZoneID"))))
    def create_s3_resources(self):
        s3_bucket = self.add_resource(
            s3.Bucket('s3TileCacheBucket',
                      BucketName=Join(
                          '.',
                          ['tile-cache',
                           Ref(self.public_hosted_zone_name)]),
                      AccessControl=s3.PublicRead,
                      CorsConfiguration=s3.CorsConfiguration(CorsRules=[
                          s3.CorsRules(
                              AllowedOrigins=['*'],
                              AllowedMethods=['GET'],
                              MaxAge=3000,
                              AllowedHeaders=['*'],
                          )
                      ])))

        self.add_resource(
            s3.BucketPolicy(
                's3TileCacheBucketPolicy',
                Bucket=Ref(s3_bucket),
                PolicyDocument={
                    'Statement': [{
                        'Action': ['s3:GetObject'],
                        'Effect': 'Allow',
                        'Resource': {
                            'Fn::Join':
                            ['', ['arn:aws:s3:::',
                                  Ref(s3_bucket), '/*']]
                        },
                        'Principal': '*'
                    }]
                }))

        self.add_resource(
            r53.RecordSetGroup(
                'dnsPublicRecordsCache',
                HostedZoneName=Join('',
                                    [Ref(self.public_hosted_zone_name), '.']),
                RecordSets=[
                    r53.RecordSet('dnsTileServersCache',
                                  AliasTarget=r53.AliasTarget(
                                      AMAZON_S3_HOSTED_ZONE_ID,
                                      AMAZON_S3_WEBSITE_DOMAIN,
                                      True,
                                  ),
                                  Name=Join('', [
                                      'tile-cache.',
                                      Ref(self.public_hosted_zone_name), '.'
                                  ]),
                                  Type='A')
                ]))
Ejemplo n.º 15
0
    def add_to_template(self, t):
        """
        """
        zone_param = ensure_param(t, self.value.output_hosted_zone(), 'String')
        dns_param = ensure_param(t, self.value.output_dns_name(), 'String')
        r = route53.RecordSet(
            '{}ELBRecord'.format(self._safe_dns_name(self.name)),
            Name="{}{}.".format(self.name, self.stack.domain_name),
            Type="A",
            AliasTarget=route53.AliasTarget(HostedZoneId=Ref(zone_param),
                                            DNSName=Ref(dns_param)))

        return r
Ejemplo n.º 16
0
def alias2resource(record, zone_name):
    name = get_resource_name(record, suffix='ALIAS')
    resource = route53.RecordSetType(name)
    resource.HostedZoneName = zone_name.ref()
    resource.Name = record['Name']
    resource.Type = record['Type']
    alias_target = route53.AliasTarget()
    alias_target.HostedZoneId = record['AliasTarget']['HostedZoneId']
    alias_target.DNSName = record['AliasTarget']['DNSName']
    alias_target.EvaluateTargetHealth = record['AliasTarget'][
        'EvaluateTargetHealth']
    resource.AliasTarget = alias_target
    return resource
Ejemplo n.º 17
0
def internal_dns_elb(context):
    # The DNS name of an existing Amazon Route 53 hosted zone
    hostedzone = context['int_domain'] + "."  # TRAILING DOT IS IMPORTANT!
    dns_record = route53.RecordSetType(R53_INT_TITLE,
                                       HostedZoneName=hostedzone,
                                       Comment="Internal DNS record for ELB",
                                       Name=context['int_full_hostname'],
                                       Type="A",
                                       AliasTarget=route53.AliasTarget(
                                           GetAtt(ELB_TITLE,
                                                  "CanonicalHostedZoneNameID"),
                                           GetAtt(ELB_TITLE, "DNSName")))
    return dns_record
Ejemplo n.º 18
0
def external_dns_elb(context):
    # http://docs.aws.amazon.com/Route53/latest/DeveloperGuide/resource-record-sets-choosing-alias-non-alias.html
    # The DNS name of an existing Amazon Route 53 hosted zone
    hostedzone = context['domain'] + "."  # TRAILING DOT IS IMPORTANT!
    dns_record = route53.RecordSetType(R53_EXT_TITLE,
                                       HostedZoneName=hostedzone,
                                       Comment="External DNS record for ELB",
                                       Name=context['full_hostname'],
                                       Type="A",
                                       AliasTarget=route53.AliasTarget(
                                           GetAtt(ELB_TITLE,
                                                  "CanonicalHostedZoneNameID"),
                                           GetAtt(ELB_TITLE, "DNSName")))
    return dns_record
Ejemplo n.º 19
0
    def add_api(self):
        api = self.add_resource(
            apigatewayv2.Api(
                'HttpApi',
                Name=StackName,
                Description=Join(' ',
                                 [Ref(self.domain), 'Terraform Registry']),
                ProtocolType='HTTP',
                Target=Ref(self._lambda_function),
            ))

        self.add_resource(
            awslambda.Permission(
                f'ApigatewayPermission',
                Principal='apigateway.amazonaws.com',
                Action='lambda:InvokeFunction',
                FunctionName=Ref(self._lambda_function),
                SourceArn=Join('', [
                    'arn:aws:execute-api:', Region, ':', AccountId, ':',
                    Ref(api), '/*'
                ])))

        domain = self.add_resource(
            apigatewayv2.DomainName('HttpApiDomain',
                                    DomainName=Ref(self.domain),
                                    DomainNameConfigurations=[
                                        apigatewayv2.DomainNameConfiguration(
                                            CertificateArn=Ref(
                                                self.certificate), )
                                    ]))

        mapping = self.add_resource(
            apigatewayv2.ApiMapping('Mapping',
                                    DomainName=Ref(domain),
                                    ApiId=Ref(api),
                                    Stage='$default'))

        dns_record = self.add_resource(
            route53.RecordSetGroup(
                'ApiDnsRecord',
                HostedZoneId=Ref(self.hosted_zone),
                RecordSets=[
                    route53.RecordSet(
                        Name=Ref(self.domain),
                        AliasTarget=route53.AliasTarget(
                            DNSName=GetAtt(domain, 'RegionalDomainName'),
                            HostedZoneId=GetAtt(domain,
                                                'RegionalHostedZoneId')),
                        Type='A')
                ]))
Ejemplo n.º 20
0
 def add_dns_alias(self, name, dns_name, zone_id, zone_name):
     """
     Helper to attach an alias dns entry to an elb
     @param dns_name [string] name of the domain
     @param zone_id [string] hostzone id for the target
     @param zone_name [string] hostzone name
     """
     return self.add_resource(
         route53.RecordSetGroup(
             name.replace(".", "") + "AliasRecordSetGroup" +
             zone_name.replace('.', ''),
             HostedZoneName=zone_name,
             RecordSets=[
                 route53.RecordSet(Name=name,
                                   Type='A',
                                   AliasTarget=route53.AliasTarget(
                                       zone_id, dns_name))
             ]))
Ejemplo n.º 21
0
 def route53_record_set(self):
     t = self.template
     t.add_resource(
         route53.RecordSetGroup(
             "RecordSetGroup",
             HostedZoneName=self.vars["HostedZone"] + ".",
             RecordSets=[
                 route53.RecordSet(
                     Name=self.vars['ServiceFqdn'] + ".",
                     Type="A",
                     AliasTarget=route53.AliasTarget(
                         HostedZoneId=get_elb_hosted_zone_id(
                             self.vars['LoadBalancerArn']),
                         DNSName=self.vars['LoadBalancerUrl'],
                     ),
                 )
             ],
         ))
     return
Ejemplo n.º 22
0
def external_dns_cloudfront(context):
    # http://docs.aws.amazon.com/Route53/latest/DeveloperGuide/resource-record-sets-choosing-alias-non-alias.html
    dns_records = []
    i = 1
    for cdn_hostname in context['cloudfront']['subdomains']:
        if _is_domain_2nd_level(cdn_hostname):
            hostedzone = cdn_hostname + "."
        else:
            hostedzone = context['domain'] + "."
        dns_records.append(
            route53.RecordSetType(
                R53_CDN_TITLE % i,
                HostedZoneName=hostedzone,
                Comment="External DNS record for Cloudfront distribution",
                Name=cdn_hostname + ".",
                Type="A",
                AliasTarget=route53.AliasTarget(
                    CLOUDFRONT_HOSTED_ZONE_ID,
                    GetAtt(CLOUDFRONT_TITLE, "DomainName"))))
        i = i + 1

    return dns_records
Ejemplo n.º 23
0
 def add_elb_dns_alias(self, elb, name, zone_name):
     """
     Helper to attach an alias dns entry to an elb
     @param elb [ELB] target elb
     @param name [string] name of the domain
     @param zone_name [string] hostzone name
     """
     if name:
         name = name.lower() + '.' + zone_name
     else:
         name = zone_name.lower()
     return self.add_resource(
         route53.RecordSetGroup(
             name.replace('.', '') + "ELBRecordSetGroup" +
             zone_name.replace('.', ''),
             HostedZoneName=zone_name.lower(),
             RecordSets=[
                 route53.RecordSet(Name=name,
                                   Type='A',
                                   AliasTarget=route53.AliasTarget(
                                       GetAtt(elb, "CanonicalHostedZoneID"),
                                       GetAtt(elb, "DNSName")))
             ]))
                Actions=[
                    elb.Action(Type="forward",
                               TargetGroupArn=Ref("{}{}TargetGroup".format(
                                   e, s)))
                ],
                Priority=priority))

        t.add_resource(
            route53.RecordSetType("{}{}DNSRecord".format(e, s),
                                  HostedZoneName=Join("", [domain, "."]),
                                  Name=Join("",
                                            [s, ".", URLPathMod, domain, "."]),
                                  Type="A",
                                  AliasTarget=route53.AliasTarget(
                                      FindInMap("RegionZIDMap",
                                                Ref("AWS::Region"), "ZoneID"),
                                      GetAtt("{}LoadBalancer".format(e),
                                             "DNSName"))))

    # Outputs

    for s in services:
        t.add_output(
            Output("{}{}TargetGroup".format(e, s),
                   Description="Target group for {} {}".format(e, s),
                   Value=Ref("{}{}TargetGroup".format(e, s)),
                   Export=Export(Sub("{}-{}-tg".format(e, s)))))

        t.add_output(
            Output("{}{}URL".format(e, s),
                   Description="Loadbalancer URL for {} in {}".format(s, e),
Ejemplo n.º 25
0
    def add_api(self):
        rest_api = self.add_resource(
            apigateway.RestApi(
                'Api',
                Description=Join(' ',
                                 [Ref(self.domain), 'Terraform Registry']),
                Name=StackName))

        methods = self.add_registry_api(rest_api)
        methods += [self.add_service_discovery_api(rest_api)]

        self.add_resource(
            awslambda.Permission(
                f'ApigatewayPermission',
                Principal='apigateway.amazonaws.com',
                Action='lambda:InvokeFunction',
                FunctionName=Ref(self._lambda_function),
                SourceArn=Join('', [
                    'arn:aws:execute-api:', Region, ':', AccountId, ':',
                    Ref(rest_api), '/*'
                ])))

        deployment_id = 'ApiDeployment' + ''.join(
            random.choice(string.ascii_letters) for _ in range(5))

        deployment = self.add_resource(
            apigateway.Deployment(deployment_id,
                                  Description=self._build_version,
                                  RestApiId=Ref(rest_api),
                                  DependsOn=methods,
                                  DeletionPolicy=Retain))

        stage = self.add_resource(
            apigateway.Stage('ApiStage',
                             MethodSettings=[
                                 apigateway.MethodSetting(
                                     HttpMethod='*',
                                     LoggingLevel='INFO',
                                     MetricsEnabled=True,
                                     ResourcePath='/*',
                                     DataTraceEnabled=True,
                                 )
                             ],
                             TracingEnabled=True,
                             StageName='prd',
                             RestApiId=Ref(rest_api),
                             DeploymentId=Ref(deployment),
                             DependsOn=[deployment]))

        domain = self.add_resource(
            apigateway.DomainName(
                'ApiDomain',
                DomainName=Ref(self.domain),
                CertificateArn=Ref(self.certificate),
                EndpointConfiguration=apigateway.EndpointConfiguration(
                    Types=['EDGE'])))

        mapping = self.add_resource(
            apigateway.BasePathMapping('Mapping',
                                       DomainName=Ref(domain),
                                       RestApiId=Ref(rest_api),
                                       Stage='prd',
                                       DependsOn=['ApiStage']))

        dns_record = self.add_resource(
            route53.RecordSetGroup('ApiDnsRecord',
                                   HostedZoneId=Ref(self.hosted_zone),
                                   RecordSets=[
                                       route53.RecordSet(
                                           Name=Ref(self.domain),
                                           AliasTarget=route53.AliasTarget(
                                               DNSName=GetAtt(
                                                   domain,
                                                   'DistributionDomainName'),
                                               HostedZoneId='Z2FDTNDATAQYW2'),
                                           Type='A')
                                   ]))
Ejemplo n.º 26
0
        HostedZoneConfig=route53.HostedZoneConfiguration(
            Comment=f'{CONFIG["STACK_NAME"]} stack HostedZone'),
    ))

t.add_resource(
    route53.RecordSetGroup(
        'HostedZoneRecordSetGroup',
        HostedZoneId=Ref(HostedZone),
        RecordSets=[
            route53.RecordSet(
                'HostedZoneAliasToCloudFront',
                Name=f'{CONFIG["DOMAIN_NAME"]}.',
                Type='A',
                AliasTarget=route53.AliasTarget(
                    HostedZoneId=
                    'Z2FDTNDATAQYW2',  # CloudFront HostedZoneId magic string
                    DNSName=GetAtt(CloudfrontDistribution, 'DomainName'),
                )),
            route53.RecordSet(
                'HostedZoneAliasToCloudFrontIpv6',
                Name=f'{CONFIG["DOMAIN_NAME"]}.',
                Type='AAAA',
                AliasTarget=route53.AliasTarget(
                    HostedZoneId=
                    'Z2FDTNDATAQYW2',  # CloudFront HostedZoneId magic string
                    DNSName=GetAtt(CloudfrontDistribution, 'DomainName'),
                ))
        ]))

if __name__ == '__main__':
Ejemplo n.º 27
0
                AcmCertificateArn=Ref(acm_cert),
                SslSupportMethod='sni-only',
            ),
        ),
        Tags=GetAtt(cloudformation_tags, 'TagList'),
    ))

hosted_zone_map = "HostedZoneMap"
template.add_mapping(hosted_zone_map, cfnutils.mappings.r53_hosted_zone_id())

template.add_resource(
    route53.RecordSetType(
        "DomainA",
        AliasTarget=route53.AliasTarget(
            DNSName=GetAtt(example_distribution, 'DomainName'),
            HostedZoneId=FindInMap(hosted_zone_map, Ref(AWS_REGION),
                                   'CloudFront'),
        ),
        Comment=Sub('DNS for ${AWS::StackName}'),
        HostedZoneName=Join('', [Ref(param_hosted_zone_name), '.']),
        Name=domain_name,
        Type='A',
    ))
template.add_resource(
    route53.RecordSetType(
        "DomainAAAA",
        AliasTarget=route53.AliasTarget(
            DNSName=GetAtt(example_distribution, 'DomainName'),
            HostedZoneId=FindInMap(hosted_zone_map, Ref(AWS_REGION),
                                   'CloudFront'),
        ),
Ejemplo n.º 28
0
        DistributionConfig=cloudfront.DistributionConfig(
            Aliases=[Ref(domain)],
            Origins=[
                cloudfront.Origin(Id=Ref(root_bucket),
                                  DomainName=GetAtt(root_bucket, 'DomainName'),
                                  S3OriginConfig=cloudfront.S3Origin())
            ],
            DefaultCacheBehavior=cloudfront.DefaultCacheBehavior(
                Compress=True,
                ForwardedValues=cloudfront.ForwardedValues(QueryString=False),
                TargetOriginId=Ref(root_bucket),
                ViewerProtocolPolicy='redirect-to-https'),
            DefaultRootObject=Ref(index_page),
            Enabled=True)))

hosted_zone = Join('', [Ref(zone), '.'])
template.add_resource(
    route53.RecordSetGroup('WebsiteDNSRecord',
                           HostedZoneName=hosted_zone,
                           Comment='Records for the root of the hosted zone',
                           RecordSets=[
                               route53.RecordSet(
                                   Name=Ref(domain),
                                   Type='A',
                                   AliasTarget=route53.AliasTarget(
                                       CLOUDFRONT_HOSTED_ZONE_ID,
                                       GetAtt(cdn, 'DomainName')))
                           ]))

print(template.to_json())
Ejemplo n.º 29
0
    def set_up_stack(self):
        """Sets up the stack"""
        if not self.INPUTS or not self.STACK_NAME_PREFIX or not self.HEALTH_ENDPOINT:
            raise MKInputError(
                'Must define INPUTS, STACK_NAME_PREFIX, and HEALTH_ENDPOINT')

        super(AppServerStack, self).set_up_stack()

        tags = self.get_input('Tags').copy()
        self.add_description('{} App Server Stack for Cac'.format(
            self.STACK_NAME_PREFIX))

        assert isinstance(tags, dict), 'tags must be a dictionary'

        self.availability_zones = get_availability_zones()

        tags.update({'StackType': 'AppServer'})
        self.default_tags = tags

        self.app_server_instance_type_parameter = self.add_parameter(
            Parameter(
                'AppServerInstanceType',
                Type='String',
                Default='t2.medium',
                Description='NAT EC2 instance type',
                AllowedValues=EC2_INSTANCE_TYPES,
                ConstraintDescription='must be a valid EC2 instance type.'),
            source='AppServerInstanceType')

        self.param_app_server_iam_profile = self.add_parameter(
            Parameter('AppServerIAMProfile',
                      Type='String',
                      Description='IAM Profile for instances'),
            source='AppServerIAMProfile')

        self.app_server_ami = self.add_parameter(Parameter(
            'AppServerAMI',
            Type='String',
            Description='{} Server EC2 AMI'.format(self.STACK_NAME_PREFIX)),
                                                 source='AppServerAMI')

        self.keyname_parameter = self.add_parameter(Parameter(
            'KeyName',
            Type='String',
            Default='cac',
            Description='Name of an existing EC2 key pair'),
                                                    source='KeyName')

        self.param_color = self.add_parameter(Parameter(
            'StackColor',
            Type='String',
            Description='Stack color',
            AllowedValues=['Blue', 'Green', 'Orange']),
                                              source='StackColor')

        self.param_stacktype = self.add_parameter(Parameter(
            'StackType',
            Type='String',
            Description='Stack type',
            AllowedValues=['Development', 'Staging', 'Production']),
                                                  source='StackType')

        self.param_public_hosted_zone_name = self.add_parameter(
            Parameter('PublicHostedZoneName',
                      Type='String',
                      Description='Public hosted zone name'),
            source='PublicHostedZoneName')

        self.param_vpc = self.add_parameter(Parameter(
            'VpcId', Type='String', Description='Name of an existing VPC'),
                                            source='VpcId')

        self.param_notification_arn = self.add_parameter(
            Parameter(
                'GlobalNotificationsARN',
                Type='String',
                Description='Physical resource ID on an AWS::SNS::Topic for '
                'notifications'),
            source='GlobalNotificationsARN')

        self.param_ssl_certificate_arn = self.add_parameter(
            Parameter('SSLCertificateARN',
                      Type='String',
                      Description=
                      'Physical resource ID on an AWS::IAM::ServerCertificate '
                      'for the application server load balancer'),
            source='SSLCertificateARN')

        self.param_public_subnets = self.add_parameter(
            Parameter('PublicSubnets',
                      Type='CommaDelimitedList',
                      Description='A list of public subnets'),
            source='AppServerPublicSubnets')

        self.param_private_subnets = self.add_parameter(
            Parameter('PrivateSubnets',
                      Type='CommaDelimitedList',
                      Description='A list of private subnets'),
            source='AppServerPrivateSubnets')

        self.param_bastion_security_group = self.add_parameter(
            Parameter('BastionSecurityGroup',
                      Type='String',
                      Description='The ID of the bastion security group'),
            source='BastionSecurityGroup')

        self.param_database_security_group = self.add_parameter(
            Parameter('DatabaseSecurityGroup',
                      Type='String',
                      Description='The ID of the database security group'),
            source='DatabaseSecurityGroup')

        self.param_nat_security_group = self.add_parameter(
            Parameter('NATSecurityGroup',
                      Type='String',
                      Description='The ID of the NAT security group'),
            source='NATSecurityGroup')

        self.param_min_size = self.add_parameter(Parameter(
            'ASGMinSize',
            Type='Number',
            Default='1',
            Description='Min size of ASG'),
                                                 source='ASGMinSize')

        self.param_max_size = self.add_parameter(Parameter(
            'ASGMaxSize',
            Type='Number',
            Default='1',
            Description='Max size of ASG'),
                                                 source='ASGMaxSize')

        self.param_desired_capacity = self.add_parameter(
            Parameter('ASGDesiredCapacity',
                      Type='Number',
                      Default='1',
                      Description='Desired capacity of ASG'),
            source='ASGDesiredCapacity')

        #
        # Security Group
        #
        app_server_load_balancer_security_group = self.add_resource(
            ec2.SecurityGroup(
                'sgAppServerLoadBalancer',
                GroupDescription=
                'Enables access to app servers via a load balancer',
                VpcId=Ref(self.param_vpc),
                SecurityGroupIngress=[
                    ec2.SecurityGroupRule(IpProtocol='tcp',
                                          CidrIp=ALLOW_ALL_CIDR,
                                          FromPort=p,
                                          ToPort=p) for p in [80, 443]
                ],
                Tags=Tags(Name='sgAppServerLoadBalancer',
                          Color=Ref(self.param_color))))

        app_server_security_group = self.add_resource(
            ec2.SecurityGroup(
                'sgAppServer',
                GroupDescription='Enables access to App Servers',
                VpcId=Ref(self.param_vpc),
                SecurityGroupIngress=[
                    ec2.SecurityGroupRule(IpProtocol='tcp',
                                          CidrIp=VPC_CIDR,
                                          FromPort=p,
                                          ToPort=p) for p in [22, 80, 443]
                ] + [
                    ec2.SecurityGroupRule(IpProtocol='tcp',
                                          SourceSecurityGroupId=Ref(sg),
                                          FromPort=80,
                                          ToPort=80)
                    for sg in [app_server_load_balancer_security_group]
                ] + [
                    ec2.SecurityGroupRule(IpProtocol='tcp',
                                          SourceSecurityGroupId=Ref(sg),
                                          FromPort=443,
                                          ToPort=443)
                    for sg in [app_server_load_balancer_security_group]
                ],
                SecurityGroupEgress=[
                    ec2.SecurityGroupRule(IpProtocol='tcp',
                                          CidrIp=ALLOW_ALL_CIDR,
                                          FromPort=p,
                                          ToPort=p)
                    for p in [80, 443, PAPERTRAIL_PORT]
                ],
                Tags=Tags(Name='sgAppServer', Color=Ref(self.param_color))))

        # ELB to App Server
        self.add_resource(
            ec2.SecurityGroupEgress(
                'sgEgressELBtoAppHTTP',
                GroupId=Ref(app_server_load_balancer_security_group),
                DestinationSecurityGroupId=Ref(app_server_security_group),
                IpProtocol='tcp',
                FromPort=80,
                ToPort=80))

        self.add_resource(
            ec2.SecurityGroupEgress(
                'sgEgressELBtoAppHTTPS',
                GroupId=Ref(app_server_load_balancer_security_group),
                DestinationSecurityGroupId=Ref(app_server_security_group),
                IpProtocol='tcp',
                FromPort=443,
                ToPort=443))

        # Bastion to App Server, app server to db, app server to inet
        rules = [(self.param_bastion_security_group, app_server_security_group,
                  [80, 443, 22]),
                 (app_server_security_group,
                  self.param_database_security_group, [POSTGRES]),
                 (app_server_security_group, self.param_nat_security_group,
                  [80, 443, 22, 587, PAPERTRAIL_PORT])]
        for num, (srcsg, destsg, ports) in enumerate(rules):
            for port in ports:
                self.add_resource(
                    ec2.SecurityGroupEgress(
                        'sgEgress{}p{}'.format(num, port),
                        GroupId=Ref(srcsg),
                        DestinationSecurityGroupId=Ref(destsg),
                        IpProtocol='tcp',
                        FromPort=port,
                        ToPort=port))
                self.add_resource(
                    ec2.SecurityGroupIngress('sgIngress{}p{}'.format(
                        num, port),
                                             GroupId=Ref(destsg),
                                             SourceSecurityGroupId=Ref(srcsg),
                                             IpProtocol='tcp',
                                             FromPort=port,
                                             ToPort=port))

        #
        # ELB
        #
        app_server_load_balancer = self.add_resource(
            elb.LoadBalancer(
                'elbAppServer',
                ConnectionDrainingPolicy=elb.ConnectionDrainingPolicy(
                    Enabled=True, Timeout=300),
                CrossZone=True,
                SecurityGroups=[Ref(app_server_load_balancer_security_group)],
                Listeners=[
                    elb.Listener(LoadBalancerPort='80',
                                 Protocol='HTTP',
                                 InstancePort='80',
                                 InstanceProtocol='HTTP'),
                    elb.Listener(LoadBalancerPort='443',
                                 Protocol='HTTPS',
                                 InstancePort='443',
                                 InstanceProtocol='HTTP',
                                 SSLCertificateId=Ref(
                                     self.param_ssl_certificate_arn))
                ],
                HealthCheck=elb.HealthCheck(
                    Target=self.HEALTH_ENDPOINT,
                    HealthyThreshold='3',
                    UnhealthyThreshold='2',
                    Interval='30',
                    Timeout='5',
                ),
                Subnets=Ref(self.param_public_subnets),
                Tags=Tags(Name='elbAppServer', Color=Ref(self.param_color))))

        self.add_resource(
            cw.Alarm('alarmAppServerBackend4xx',
                     AlarmActions=[Ref(self.param_notification_arn)],
                     Statistic='Sum',
                     Period=300,
                     Threshold='5',
                     EvaluationPeriods=1,
                     ComparisonOperator='GreaterThanThreshold',
                     MetricName='HTTPCode_Backend_4XX',
                     Namespace='AWS/ELB',
                     Dimensions=[
                         cw.MetricDimension(
                             'metricLoadBalancerName',
                             Name='LoadBalancerName',
                             Value=Ref(app_server_load_balancer))
                     ]))

        self.add_resource(
            cw.Alarm('alarmAppServerBackend5xx',
                     AlarmActions=[Ref(self.param_notification_arn)],
                     Statistic='Sum',
                     Period=60,
                     Threshold='0',
                     EvaluationPeriods=1,
                     ComparisonOperator='GreaterThanThreshold',
                     MetricName='HTTPCode_Backend_5XX',
                     Namespace='AWS/ELB',
                     Dimensions=[
                         cw.MetricDimension(
                             'metricLoadBalancerName',
                             Name='LoadBalancerName',
                             Value=Ref(app_server_load_balancer))
                     ]))

        #
        # ASG
        #
        app_server_launch_config = self.add_resource(
            asg.LaunchConfiguration(
                'lcAppServer',
                ImageId=Ref(self.app_server_ami),
                IamInstanceProfile=Ref(self.param_app_server_iam_profile),
                InstanceType=Ref(self.app_server_instance_type_parameter),
                KeyName=Ref(self.keyname_parameter),
                SecurityGroups=[Ref(app_server_security_group)]))

        autoscaling_group = self.add_resource(
            asg.AutoScalingGroup(
                'asgAppServer',
                AvailabilityZones=self.get_input(
                    'AppServerAvailabilityZones').split(','),
                Cooldown=300,
                DesiredCapacity=Ref(self.param_desired_capacity),
                HealthCheckGracePeriod=600,
                HealthCheckType='ELB',
                LaunchConfigurationName=Ref(app_server_launch_config),
                LoadBalancerNames=[Ref(app_server_load_balancer)],
                MaxSize=Ref(self.param_max_size),
                MinSize=Ref(self.param_min_size),
                NotificationConfiguration=asg.NotificationConfiguration(
                    TopicARN=Ref(self.param_notification_arn),
                    NotificationTypes=[
                        asg.EC2_INSTANCE_LAUNCH, asg.EC2_INSTANCE_LAUNCH_ERROR,
                        asg.EC2_INSTANCE_TERMINATE,
                        asg.EC2_INSTANCE_TERMINATE_ERROR
                    ]),
                VPCZoneIdentifier=Ref(self.param_private_subnets),
                Tags=[
                    asg.Tag('Name', '{}Server'.format(self.STACK_NAME_PREFIX),
                            True),
                    asg.Tag('Color', Ref(self.param_color), True)
                ]))

        # autoscaling policies
        autoscaling_policy_add = self.add_resource(
            asg.ScalingPolicy('scalingPolicyAddAppServer',
                              AdjustmentType='ChangeInCapacity',
                              AutoScalingGroupName=Ref(autoscaling_group),
                              Cooldown=600,
                              ScalingAdjustment='1'))

        autoscaling_policy_remove = self.add_resource(
            asg.ScalingPolicy('scalingPolicyRemoveAppServer',
                              AdjustmentType='ChangeInCapacity',
                              AutoScalingGroupName=Ref(autoscaling_group),
                              Cooldown=600,
                              ScalingAdjustment='-1'))

        if self.STACK_NAME_PREFIX == 'Otp':
            # trigger scale down if CPU avg usage < 10% for 3 consecutive 5 min periods
            self.add_resource(
                cw.Alarm('alarmAppServerLowCPU',
                         AlarmActions=[Ref(autoscaling_policy_remove)],
                         Statistic='Average',
                         Period=300,
                         Threshold='10',
                         EvaluationPeriods=3,
                         ComparisonOperator='LessThanThreshold',
                         MetricName='CPUUtilization',
                         Namespace='AWS/EC2',
                         Dimensions=[
                             cw.MetricDimension('metricAutoScalingGroupName',
                                                Name='AutoScalingGroupName',
                                                Value=Ref(autoscaling_group))
                         ]))

            # trigger scale up if CPU avg usage >= 30% for a 5 min period
            self.add_resource(
                cw.Alarm('alarmAppServerHighCPU',
                         AlarmActions=[
                             Ref(self.param_notification_arn),
                             Ref(autoscaling_policy_add)
                         ],
                         Statistic='Average',
                         Period=300,
                         Threshold='30',
                         EvaluationPeriods=1,
                         ComparisonOperator='GreaterThanOrEqualToThreshold',
                         MetricName='CPUUtilization',
                         Namespace='AWS/EC2',
                         Dimensions=[
                             cw.MetricDimension('metricAutoScalingGroupName',
                                                Name='AutoScalingGroupName',
                                                Value=Ref(autoscaling_group))
                         ]))
        else:
            # scale web servers based on network usage
            self.add_resource(
                cw.Alarm('alarmAppServerLowNetworkUsage',
                         AlarmActions=[Ref(autoscaling_policy_remove)],
                         Statistic='Average',
                         Period=300,
                         Threshold='500000',
                         EvaluationPeriods=3,
                         ComparisonOperator='LessThanThreshold',
                         MetricName='NetworkOut',
                         Namespace='AWS/EC2',
                         Dimensions=[
                             cw.MetricDimension('metricAutoScalingGroupName',
                                                Name='AutoScalingGroupName',
                                                Value=Ref(autoscaling_group))
                         ]))

            self.add_resource(
                cw.Alarm('alarmAppServerHighNetworkUsage',
                         AlarmActions=[
                             Ref(self.param_notification_arn),
                             Ref(autoscaling_policy_add)
                         ],
                         Statistic='Average',
                         Period=300,
                         Threshold='10000000',
                         EvaluationPeriods=1,
                         ComparisonOperator='GreaterThanOrEqualToThreshold',
                         MetricName='NetworkOut',
                         Namespace='AWS/EC2',
                         Dimensions=[
                             cw.MetricDimension('metricAutoScalingGroupName',
                                                Name='AutoScalingGroupName',
                                                Value=Ref(autoscaling_group))
                         ]))

        #
        # DNS name
        #
        self.create_resource(
            route53.RecordSetType(
                'dnsName',
                Name=Join('.', [
                    Ref(self.param_color),
                    Ref(self.param_stacktype), self.STACK_NAME_PREFIX,
                    Ref(self.param_public_hosted_zone_name)
                ]),
                Type='A',
                AliasTarget=route53.AliasTarget(
                    GetAtt(app_server_load_balancer,
                           'CanonicalHostedZoneNameID'),
                    GetAtt(app_server_load_balancer, 'DNSName')),
                HostedZoneName=Ref(self.param_public_hosted_zone_name)))

        self.add_output([
            Output('{}ServerLoadBalancerEndpoint'.format(
                self.STACK_NAME_PREFIX),
                   Description='Application server endpoint',
                   Value=GetAtt(app_server_load_balancer, 'DNSName')),
            Output('{}ServerLoadBalancerHostedZoneNameID'.format(
                self.STACK_NAME_PREFIX),
                   Description='ID of canonical hosted zone name for ELB',
                   Value=GetAtt(app_server_load_balancer,
                                'CanonicalHostedZoneNameID'))
        ])
Ejemplo n.º 30
0
            ],
            PriceClass='PriceClass_100',
            ViewerCertificate=cloudfront.ViewerCertificate(
                AcmCertificateArn=Ref(certificate),
                SslSupportMethod='sni-only',
            ))))

record_set_group = template.add_resource(
    route53.RecordSetGroup(
        'RecordSetGroup',
        HostedZoneId=Ref(hosted_zone_id),
        RecordSets=[
            route53.RecordSet(Name=Ref(domain),
                              Type='A',
                              AliasTarget=route53.AliasTarget(
                                  HostedZoneId=CLOUDFRONT_HOSTED_ZONE_ID,
                                  DNSName=GetAtt(distribution, 'DomainName'),
                              )),
        ]))
# endregion

# region Outputs
template.add_output(Output('Distribution', Value=Ref(distribution)))
# endregion

# region Metadata
template.add_metadata({
    'AWS::CloudFormation::Interface': {
        'ParameterLabels': {
            # Project
            email.title: {
                'default': 'Notifications'