Beispiel #1
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
Beispiel #2
0
    def test_acm_non_alphanumeric(self):
        project_config = ProjectConfig(
            'tests/cloudformation/sample-project_acm.yaml', 'dev')
        config_parser = ConfigParser(project_config.config, 'my-stack-name')
        certificate_name = 'mycert-dev.something.io'
        parsed_certificate_name = 'mycertdevsomethingio'
        domain_name = 'helloworld.test.dsd.io'
        tags = [{
            'Key': 'Name',
            'Value': {
                'Fn::Join': ['', [{
                    'Ref': u'AWS::StackName'
                }, '-', u'acm']]
            }
        }]
        subject_alternative_names = []

        domain_validation_options = DomainValidationOption(
            DomainName=domain_name, ValidationDomain=domain_name)
        ACMCertificate = Certificate(
            parsed_certificate_name,
            DomainName=domain_name,
            SubjectAlternativeNames=subject_alternative_names,
            DomainValidationOptions=[domain_validation_options],
            Tags=tags)
        certificate_cfg = [
            config_parser._get_acm_certificate(certificate_name)
        ]
        expected = [ACMCertificate]
        compare(self._resources_to_dict(expected),
                self._resources_to_dict(certificate_cfg))
Beispiel #3
0
def create_acm_certificate(stack, domain_name, alternate_names=[]):
    """Add ACM Certificate Resource."""
    return stack.stack.add_resource(Certificate(
        'mycert',
        DomainName='{0}'.format(domain_name),
        SubjectAlternativeNames=alternate_names,
        DomainValidationOptions=[
            DomainValidationOption(
                DomainName='{0}'.format(domain_name),
                ValidationDomain='{0}'.format(domain_name),
            ),
        ],
    ))
Beispiel #4
0
    def test_acm(self):
        project_config = ProjectConfig(
            'tests/cloudformation/sample-project_acm.yaml', 'dev')
        config_parser = ConfigParser(project_config.config, 'my-stack-name')
        certificate_name = 'mycert'
        domain_name = 'helloworld.test.dsd.io'
        validation_domain = 'dsd.io'
        tags = [{
            'Key': 'Name',
            'Value': {
                'Fn::Join': ['', [{
                    'Ref': u'AWS::StackName'
                }, '-', u'acm']]
            }
        }, {
            'Key': 'test_key1',
            'Value': 'test_value_1'
        }, {
            'Key': 'test_key2',
            'Value': 'test_value_2'
        }]
        subject_alternative_names = [
            'goodbye.test.somewhere.io', 'hello_again.subdomain.dsd.io'
        ]

        # The main domain should use validation_domain,
        # 'goodbye.test.somewhere.io' should use the domain_validation_options
        # to validate on somewhere.io.
        # 'hello_again.subdomain.dsd.io' has no validation_options so should
        # default to the validation_domain
        domain_validation_options = [
            DomainValidationOption(DomainName=domain_name,
                                   ValidationDomain=validation_domain),
            DomainValidationOption(DomainName='goodbye.test.somewhere.io',
                                   ValidationDomain='somewhere.io'),
            DomainValidationOption(DomainName='hello_again.subdomain.dsd.io',
                                   ValidationDomain=validation_domain)
        ]
        ACMCertificate = Certificate(
            certificate_name,
            DomainName=domain_name,
            SubjectAlternativeNames=subject_alternative_names,
            DomainValidationOptions=domain_validation_options,
            Tags=tags)
        certificate_cfg = [
            config_parser._get_acm_certificate(certificate_name)
        ]
        expected = [ACMCertificate]
        compare(self._resources_to_dict(expected),
                self._resources_to_dict(certificate_cfg))
)
custom_app_certificate_arn_condition = "CustomAppCertArnCondition"
template.add_condition(custom_app_certificate_arn_condition, Not(Equals(Ref(custom_app_certificate_arn), "")))

stack_cert_condition = "StackCertificateCondition"
template.add_condition(stack_cert_condition, Not(Equals(Ref(certificate_validation_method), dont_create_value)))

cert_condition = "CertificateCondition"
template.add_condition(cert_condition, Or(
    Not(Equals(Ref(custom_app_certificate_arn), "")),
    Not(Equals(Ref(certificate_validation_method), dont_create_value))
))

application = If(custom_app_certificate_arn_condition,
                 Ref(custom_app_certificate_arn),
                 Ref(template.add_resource(
                     Certificate(
                         'Certificate',
                         Condition=stack_cert_condition,
                         DomainName=domain_name,
                         SubjectAlternativeNames=If(no_alt_domains, Ref("AWS::NoValue"), domain_name_alternates),
                         DomainValidationOptions=[
                             DomainValidationOption(
                                 DomainName=domain_name,
                                 ValidationDomain=domain_name,
                             ),
                         ],
                         ValidationMethod=Ref(certificate_validation_method)
                     )
                 )))
Beispiel #6
0
    def __init__(self,
                 utils,
                 templatePath='./cloudformation/api.json',
                 description='Top Level API Gateway Template for {App}',
                 version='2010-09-09'):
        super(self.__class__, self).__init__()

        self.utils = utils
        self.templatePath = templatePath
        appName = self.utils.config['App']
        domainName = self.utils.config['Domain']
        tags = self.utils.config['Tags']

        self.add_version(version)
        self.add_description(description.format(App=appName))

        ###################
        # ACM Certificate #
        ###################

        self.certificate = self.add_resource(
            Certificate(
                '{App}Certificate'.format(App=appName),
                DomainName=domainName,
                SubjectAlternativeNames=[
                    '*.{Domain}'.format(Domain=domainName)
                ],
                Tags=Tags(tags),
            ))

        #####################
        # Deployment Bucket #
        #####################

        self.bucket = self.add_resource(
            Bucket(
                '{App}DeploymentBucket'.format(App=appName),
                DeletionPolicy='Retain',
                Tags=Tags(tags),
                VersioningConfiguration=VersioningConfiguration(
                    Status='Enabled', ),
            ))

        ###########
        # RestApi #
        ###########

        self.api = self.add_resource(
            RestApi(
                '{App}Api'.format(App=appName),
                Name=appName + 'Api',
                Description='API for {App} AWS SAML Login Redirection'.format(
                    App=appName),
            ))

        ##################
        # RestApi Domain #
        ##################

        self.apiDomain = self.add_resource(
            DomainName(
                '{App}ApiDomainName'.format(App=appName),
                CertificateArn=Ref(self.certificate),
                DomainName=domainName,
            ))

        self.apiDomainMapping = self.add_resource(
            BasePathMapping(
                '{App}ApiDomainNameMapping'.format(App=appName),
                DomainName=Ref(self.apiDomain),
                RestApiId=Ref(self.api),
            ))

        ###########
        # Outputs #
        ###########

        self.add_output(
            Output(
                '{App}Api'.format(App=appName),
                Value=Ref(self.api),
                Export=Export('{App}Api'.format(App=appName), ),
            ))

        self.add_output(
            Output(
                '{App}ApiDomainName'.format(App=appName),
                Value=Ref(self.apiDomain),
                Export=Export('{App}ApiDomainName'.format(App=appName), ),
            ))

        self.add_output(
            Output(
                '{App}ApiDomainDistribution'.format(App=appName),
                Value=GetAtt(self.apiDomain, 'DistributionDomainName'),
                Export=Export(
                    '{App}ApiDomainDistribution'.format(App=appName), ),
            ))

        self.add_output(
            Output(
                '{App}ApiRoot'.format(App=appName),
                Value=GetAtt(self.api, 'RootResourceId'),
                Export=Export('{App}ApiRoot'.format(App=appName), ),
            ))

        self.add_output(
            Output(
                '{App}Certificate'.format(App=appName),
                Value=Ref(self.certificate),
                Export=Export('{App}Certificate'.format(App=appName), ),
            ))

        self.add_output(
            Output(
                '{App}DeploymentBucket'.format(App=appName),
                Value=Ref(self.bucket),
                Export=Export('{App}DeploymentBucket'.format(App=appName), ),
            ))

        ##################
        # Write Template #
        ##################

        with open(templatePath, 'w') as templateFile:
            templateFile.write(self.to_json())
Beispiel #7
0
    # Currently, you can specify only certificates that are in the US East (N. Virginia) region.
    # http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cloudfront-distributionconfig-viewercertificate.html
    assets_custom_domain_and_us_east_1_condition = "AssetsCloudFrontDomainAndUsEast1Condition"
    template.add_condition(
        assets_custom_domain_and_us_east_1_condition,
        And(Not(Equals(Ref(assets_cloudfront_domain), "")),
            Equals(Ref(AWS_REGION), "us-east-1")))

    assets_certificate = template.add_resource(
        Certificate(
            'AssetsCertificate',
            Condition=assets_custom_domain_and_us_east_1_condition,
            DomainName=Ref(assets_cloudfront_domain),
            DomainValidationOptions=[
                DomainValidationOption(
                    DomainName=Ref(assets_cloudfront_domain),
                    ValidationDomain=Ref(assets_cloudfront_domain),
                ),
            ],
        ))

    assets_certificate_arn = template.add_parameter(
        Parameter(
            "AssetsCloudFrontCertArn",
            Description=
            "If (1) you specified a custom static media domain, (2) your stack is NOT in the us-east-1 "
            "region, and (3) you wish to serve static media over HTTPS, you must manually create an "
            "ACM certificate in the us-east-1 region and provide its ARN here.",
            Type="String",
        ),
Beispiel #8
0
from troposphere import Template
from troposphere.certificatemanager import Certificate, DomainValidationOption

t = Template()

t.add_resource(
    Certificate(
        'mycert',
        DomainName='example.com',
        DomainValidationOptions=[
            DomainValidationOption(
                DomainName='example.com',
                ValidationDomain='example.com',
            ),
        ],
        Tags=[
            {
                'Key': 'tag-key',
                'Value': 'tag-value'
            },
        ],
    ))

print(t.to_json())
Beispiel #9
0
from troposphere import Ref
from troposphere.certificatemanager import Certificate, DomainValidationOption

from .domain import domain_name
from .template import template

application = Ref(
    template.add_resource(
        Certificate(
            'Certificate',
            DomainName=domain_name,
            DomainValidationOptions=[
                DomainValidationOption(
                    DomainName=domain_name,
                    ValidationDomain=domain_name,
                ),
            ],
        )))
    def __init__(self,
                 prefix: str,
                 lb_security_groups: List[SecurityGroup],
                 subnets: List[Subnet],
                 vpc: VPC,
                 desired_domain_name: str,
                 healthy_http_codes: Optional[List[int]] = None):
        """
        Constructor.

        :param prefix: A prefix for resource names.
        :param lb_security_groups: Security groups to attach to a loadbalancer. NOTE! when passing loadbalancer
        security groups - make sure the loadbalancer can communicate through ci/cd blue/green deployments
        opened ports. Usually they are 8000 and 44300.
        :param subnets: Subnets in which loadbalancer can exist.
        :param vpc: Virtual private cloud in which target groups and a loadbalancer exist.
        :param desired_domain_name: Domain name for using https.
        :param healthy_http_codes: The deployed instance is constantly pinged to determine if it is available
        (healthy) or not. Specify a list of http codes that your service can return and should be treated as healthy.
        """
        # By default a healthy http code is considered to be 200.
        healthy_http_codes = healthy_http_codes or [200]

        # If your service's task definition uses the awsvpc network mode
        # (which is required for the Fargate launch type), you must choose ip as the target type,
        # not instance, when creating your target groups because
        # tasks that use the awsvpc network mode are associated with an elastic network interface,
        # not an Amazon EC2 instance.
        self.target_type = 'ip'

        # Certificate so a loadbalancer could communicate via HTTPS.
        self.certificate = Certificate(
            prefix + 'FargateEcsCertificate',
            DomainName=desired_domain_name,
            ValidationMethod='DNS',
        )

        # A main target group to which a loadbalancer forwards a HTTP traffic.
        # This is the main group with which our ecs container is associated.
        self.target_group_1_http = TargetGroup(
            prefix + 'FargateEcsTargetGroup1',
            Name=prefix + 'FargateEcsTargetGroup1',
            Matcher=Matcher(
                HttpCode=','.join([str(code) for code in healthy_http_codes])),
            Port=self.TARGET_GROUP_PORT,
            Protocol='HTTP',
            VpcId=Ref(vpc),
            TargetType=self.target_type)

        # Second target group is usd for Blue/Green deployments. A new container (that should be deployed)
        # is associated with the second target group.
        self.target_group_2_http = TargetGroup(
            prefix + 'FargateEcsTargetGroup2',
            Name=prefix + 'FargateEcsTargetGroup2',
            Matcher=Matcher(
                HttpCode=','.join([str(code) for code in healthy_http_codes])),
            Port=self.TARGET_GROUP_PORT,
            Protocol='HTTP',
            VpcId=Ref(vpc),
            TargetType=self.target_type)

        self.load_balancer = LoadBalancer(
            prefix + 'FargateEcsLoadBalancer',
            Subnets=[Ref(sub) for sub in subnets],
            SecurityGroups=[Ref(group) for group in lb_security_groups],
            Name=prefix + 'FargateEcsLoadBalancer',
            Scheme='internet-facing',
        )

        self.load_balancer_output = Output(
            prefix + 'FargateEcsLoadBalancerUrl',
            Description='The endpoint url of a loadbalancer.',
            Value=GetAtt(self.load_balancer, 'DNSName'))

        # Listener that listens to HTTP incoming traffic and redirects to other HTTPS listener.
        self.listener_http_1 = Listener(
            prefix + 'FargateEcsHttpListener1',
            Port=self.LISTENER_HTTP_PORT_1,
            Protocol='HTTP',
            LoadBalancerArn=Ref(self.load_balancer),
            DefaultActions=[
                # Redirect to https.
                Action(Type='redirect',
                       RedirectConfig=RedirectConfig(
                           Host='#{host}',
                           Path='/#{path}',
                           Port=str(self.LISTENER_HTTPS_PORT_1),
                           Query='#{query}',
                           StatusCode='HTTP_301',
                           Protocol='HTTPS'))
            ])

        # Listener that listens to HTTPS traffic and forwards to a target group.
        self.listener_https_1 = Listener(
            prefix + 'FargateEcsHttpsListener1',
            Certificates=[LBCertificate(CertificateArn=Ref(self.certificate))],
            Port=self.LISTENER_HTTPS_PORT_1,
            Protocol='HTTPS',
            LoadBalancerArn=Ref(self.load_balancer),
            DefaultActions=[
                Action(Type='forward',
                       TargetGroupArn=Ref(self.target_group_1_http))
            ])

        # Second listener is usd for Blue/Green deployments (testing new instance). Test HTTP traffic is
        # redirected to test HTTPS traffic.
        self.listener_http_2 = Listener(
            prefix + 'FargateEcsHttpListener2',
            Port=self.LISTENER_HTTP_PORT_2,
            Protocol='HTTP',
            LoadBalancerArn=Ref(self.load_balancer),
            DefaultActions=[
                # Redirect to https.
                Action(Type='redirect',
                       RedirectConfig=RedirectConfig(
                           Host='#{host}',
                           Path='/#{path}',
                           Port=str(self.LISTENER_HTTPS_PORT_2),
                           Query='#{query}',
                           StatusCode='HTTP_301',
                           Protocol='HTTPS'))
            ])

        # Listener that listens to test HTTP traffic and forwards to a secondary target group (new container).
        self.listener_https_2 = Listener(
            prefix + 'FargateEcsHttpsListener2',
            Certificates=[LBCertificate(CertificateArn=Ref(self.certificate))],
            Port=self.LISTENER_HTTPS_PORT_2,
            Protocol='HTTPS',
            LoadBalancerArn=Ref(self.load_balancer),
            DefaultActions=[
                Action(Type='forward',
                       TargetGroupArn=Ref(self.target_group_2_http))
            ])
Beispiel #11
0
    ))

domain_name = template.add_parameter(
    Parameter(
        'DomainName',
        Type=constants.STRING,
        Default='videos.spunt.be',
    ))

cloudfront_certificate = template.add_resource(
    Certificate(
        "CloudFrontCertificate",
        DomainName=Ref(domain_name),
        DomainValidationOptions=[
            DomainValidationOption(
                DomainName=Ref(domain_name),
                ValidationDomain=ImportValue(
                    Join('-', [Ref(dns_stack), 'HostedZoneName'])),
            )
        ],
        ValidationMethod='DNS',
    ))

video_cdn = template.add_resource(
    Distribution(
        "VideoDistribution",
        DistributionConfig=DistributionConfig(
            Aliases=[Ref(domain_name)],
            Comment=Ref(AWS_STACK_NAME),
            DefaultCacheBehavior=DefaultCacheBehavior(
                TargetOriginId='S3',
                ViewerProtocolPolicy='redirect-to-https',
from troposphere import Template
from troposphere.certificatemanager import Certificate, DomainValidationOption

t = Template()

t.add_resource(
    Certificate(
        "mycert",
        DomainName="example.com",
        DomainValidationOptions=[
            DomainValidationOption(
                DomainName="example.com",
                ValidationDomain="example.com",
            ),
        ],
        Tags=[
            {
                "Key": "tag-key",
                "Value": "tag-value"
            },
        ],
    ))

print(t.to_json())
Beispiel #13
0
zone_set_cond = t.add_condition(
    'zoneIdSet',
    Not(Equals(Ref(zone_id), ''))
)

#############
# Resources
#############

# SSL cert for CloudFront
ssl_certificate = t.add_resource(Certificate(
    'myCert',
    DomainName              = Ref(domain_name),
    DomainValidationOptions = [
        DomainValidationOption(
            DomainName          = Ref(domain_name),
            ValidationDomain    = Ref(zone_apex),
        ),
    ],
))

s3_bucket = t.add_resource(Bucket('myBucket'))

bucket_policy = t.add_resource(BucketPolicy(
    'myBucketPolicy',
    Bucket          = Ref(s3_bucket),
    PolicyDocument  = {
        'Version'   : '2012-10-17',
        'Id'        : 'PolicyForCloudFrontPrivateContent',
        'Statement' : [
            {
        Default='rob-kenis-dot-com-dns',
        Description=
        'Name of the CloudFormation stack that holds the HostedZone',
    ))

cloudfront_certificate = template.add_resource(
    Certificate(
        "CloudFrontCertificate",
        DomainName='robkenis.com',
        SubjectAlternativeNames=['www.robkenis.com'],
        ValidationMethod='DNS',
        DomainValidationOptions=[
            DomainValidationOption(
                DomainName='robkenis.com',
                HostedZoneId=ImportValue(
                    Join('-', [Ref(dns_stack), 'HostedZoneId'])),
            ),
            DomainValidationOption(
                DomainName='www.robkenis.com',
                HostedZoneId=ImportValue(
                    Join('-', [Ref(dns_stack), 'HostedZoneId'])),
            ),
        ],
        Tags=Tags({'Name': Ref(AWS_STACK_NAME)}),
    ))

s3_website_origin = template.add_resource(
    Bucket(
        'WebsiteOrigin',
        AccessControl='Private',
    ))
Beispiel #15
0
def create_template():
    template = Template(Description=(
        "Static website hosted with S3 and CloudFront. "
        "https://github.com/schlarpc/overengineered-cloudfront-s3-static-website"
    ))

    partition_config = add_mapping(
        template,
        "PartitionConfig",
        {
            "aws": {
                # the region with the control plane for CloudFront, IAM, Route 53, etc
                "PrimaryRegion":
                "us-east-1",
                # assume that Lambda@Edge replicates to all default enabled regions, and that
                # future regions will be opt-in. generated with AWS CLI:
                # aws ec2 describe-regions --all-regions --query "Regions[?OptInStatus=='opt-in-not-required'].RegionName|sort(@)"
                "DefaultRegions": [
                    "ap-northeast-1",
                    "ap-northeast-2",
                    "ap-northeast-3",
                    "ap-south-1",
                    "ap-southeast-1",
                    "ap-southeast-2",
                    "ca-central-1",
                    "eu-central-1",
                    "eu-north-1",
                    "eu-west-1",
                    "eu-west-2",
                    "eu-west-3",
                    "sa-east-1",
                    "us-east-1",
                    "us-east-2",
                    "us-west-1",
                    "us-west-2",
                ],
            },
            # this doesn't actually work, because Lambda@Edge isn't supported in aws-cn
            "aws-cn": {
                "PrimaryRegion": "cn-north-1",
                "DefaultRegions": ["cn-north-1", "cn-northwest-1"],
            },
        },
    )

    acm_certificate_arn = template.add_parameter(
        Parameter(
            "AcmCertificateArn",
            Description=
            "Existing ACM certificate to use for serving TLS. Overrides HostedZoneId.",
            Type="String",
            AllowedPattern="(arn:[^:]+:acm:[^:]+:[^:]+:certificate/.+|)",
            Default="",
        ))

    hosted_zone_id = template.add_parameter(
        Parameter(
            "HostedZoneId",
            Description=
            "Existing Route 53 zone to use for validating a new TLS certificate.",
            Type="String",
            AllowedPattern="(Z[A-Z0-9]+|)",
            Default="",
        ))

    dns_names = template.add_parameter(
        Parameter(
            "DomainNames",
            Description=
            "Comma-separated list of additional domain names to serve.",
            Type="CommaDelimitedList",
            Default="",
        ))

    tls_protocol_version = template.add_parameter(
        Parameter(
            "TlsProtocolVersion",
            Description=
            "CloudFront TLS security policy; see https://amzn.to/2DR91Xq for details.",
            Type="String",
            Default="TLSv1.2_2019",
        ))

    log_retention_days = template.add_parameter(
        Parameter(
            "LogRetentionDays",
            Description=
            "Days to keep CloudFront, S3, and Lambda logs. 0 means indefinite retention.",
            Type="Number",
            AllowedValues=[0] + CLOUDWATCH_LOGS_RETENTION_OPTIONS,
            Default=365,
        ))

    default_ttl_seconds = template.add_parameter(
        Parameter(
            "DefaultTtlSeconds",
            Description="Cache time-to-live when not set by S3 object headers.",
            Type="Number",
            Default=int(datetime.timedelta(minutes=5).total_seconds()),
        ))

    enable_price_class_hack = template.add_parameter(
        Parameter(
            "EnablePriceClassHack",
            Description="Cut your bill in half with this one weird trick.",
            Type="String",
            Default="false",
            AllowedValues=["true", "false"],
        ))

    retention_defined = add_condition(template, "RetentionDefined",
                                      Not(Equals(Ref(log_retention_days), 0)))

    using_price_class_hack = add_condition(
        template, "UsingPriceClassHack",
        Equals(Ref(enable_price_class_hack), "true"))

    using_acm_certificate = add_condition(
        template, "UsingAcmCertificate",
        Not(Equals(Ref(acm_certificate_arn), "")))

    using_hosted_zone = add_condition(template, "UsingHostedZone",
                                      Not(Equals(Ref(hosted_zone_id), "")))

    using_certificate = add_condition(
        template,
        "UsingCertificate",
        Or(Condition(using_acm_certificate), Condition(using_hosted_zone)),
    )

    should_create_certificate = add_condition(
        template,
        "ShouldCreateCertificate",
        And(Condition(using_hosted_zone),
            Not(Condition(using_acm_certificate))),
    )

    using_dns_names = add_condition(template, "UsingDnsNames",
                                    Not(Equals(Select(0, Ref(dns_names)), "")))

    is_primary_region = "IsPrimaryRegion"
    template.add_condition(
        is_primary_region,
        Equals(Region, FindInMap(partition_config, Partition,
                                 "PrimaryRegion")),
    )

    precondition_region_is_primary = template.add_resource(
        WaitConditionHandle(
            "PreconditionIsPrimaryRegionForPartition",
            Condition=is_primary_region,
        ))

    log_ingester_dlq = template.add_resource(
        Queue(
            "LogIngesterDLQ",
            MessageRetentionPeriod=int(
                datetime.timedelta(days=14).total_seconds()),
            KmsMasterKeyId="alias/aws/sqs",
        ))

    log_ingester_role = template.add_resource(
        Role(
            "LogIngesterRole",
            AssumeRolePolicyDocument=PolicyDocument(
                Version="2012-10-17",
                Statement=[
                    Statement(
                        Effect="Allow",
                        Principal=Principal("Service", "lambda.amazonaws.com"),
                        Action=[sts.AssumeRole],
                    )
                ],
            ),
            Policies=[
                PolicyProperty(
                    PolicyName="DLQPolicy",
                    PolicyDocument=PolicyDocument(
                        Version="2012-10-17",
                        Statement=[
                            Statement(
                                Effect=Allow,
                                Action=[sqs.SendMessage],
                                Resource=[GetAtt(log_ingester_dlq, "Arn")],
                            )
                        ],
                    ),
                )
            ],
        ))

    log_ingester = template.add_resource(
        Function(
            "LogIngester",
            Runtime=PYTHON_RUNTIME,
            Handler="index.{}".format(log_ingest.handler.__name__),
            Code=Code(ZipFile=inspect.getsource(log_ingest)),
            MemorySize=256,
            Timeout=300,
            Role=GetAtt(log_ingester_role, "Arn"),
            DeadLetterConfig=DeadLetterConfig(
                TargetArn=GetAtt(log_ingester_dlq, "Arn")),
        ))

    log_ingester_permission = template.add_resource(
        Permission(
            "LogIngesterPermission",
            FunctionName=GetAtt(log_ingester, "Arn"),
            Action="lambda:InvokeFunction",
            Principal="s3.amazonaws.com",
            SourceAccount=AccountId,
        ))

    log_bucket = template.add_resource(
        Bucket(
            "LogBucket",
            # S3 requires this ACL (regardless of bucket policy) or s3:PutBucketLogging fails.
            # When the CloudFront distribution is created, it adds an additional bucket ACL.
            # That ACL is not possible to model in CloudFormation.
            AccessControl="LogDeliveryWrite",
            LifecycleConfiguration=LifecycleConfiguration(Rules=[
                LifecycleRule(ExpirationInDays=1, Status="Enabled"),
                LifecycleRule(
                    AbortIncompleteMultipartUpload=
                    AbortIncompleteMultipartUpload(DaysAfterInitiation=1),
                    Status="Enabled",
                ),
            ]),
            NotificationConfiguration=NotificationConfiguration(
                LambdaConfigurations=[
                    LambdaConfigurations(Event="s3:ObjectCreated:*",
                                         Function=GetAtt(log_ingester, "Arn"))
                ]),
            BucketEncryption=BucketEncryption(
                ServerSideEncryptionConfiguration=[
                    ServerSideEncryptionRule(
                        ServerSideEncryptionByDefault=
                        ServerSideEncryptionByDefault(
                            # if we use KMS, we can't read the logs
                            SSEAlgorithm="AES256"))
                ]),
            OwnershipControls=OwnershipControls(Rules=[
                OwnershipControlsRule(ObjectOwnership="BucketOwnerPreferred")
            ], ),
            PublicAccessBlockConfiguration=PublicAccessBlockConfiguration(
                BlockPublicAcls=True,
                BlockPublicPolicy=True,
                IgnorePublicAcls=True,
                RestrictPublicBuckets=True,
            ),
            DependsOn=[log_ingester_permission],
        ))

    log_ingester_log_group = template.add_resource(
        LogGroup(
            "LogIngesterLogGroup",
            LogGroupName=Join(
                "", ["/aws/lambda/", Ref(log_ingester)]),
            RetentionInDays=If(retention_defined, Ref(log_retention_days),
                               NoValue),
        ))

    log_ingester_policy = template.add_resource(
        PolicyType(
            "LogIngesterPolicy",
            Roles=[Ref(log_ingester_role)],
            PolicyName="IngestLogPolicy",
            PolicyDocument=PolicyDocument(
                Version="2012-10-17",
                Statement=[
                    Statement(
                        Effect=Allow,
                        Action=[logs.CreateLogStream, logs.PutLogEvents],
                        Resource=[
                            Join(
                                ":",
                                [
                                    "arn",
                                    Partition,
                                    "logs",
                                    Region,
                                    AccountId,
                                    "log-group",
                                    "/aws/cloudfront/*",
                                ],
                            ),
                            Join(
                                ":",
                                [
                                    "arn",
                                    Partition,
                                    "logs",
                                    Region,
                                    AccountId,
                                    "log-group",
                                    "/aws/s3/*",
                                ],
                            ),
                            GetAtt(log_ingester_log_group, "Arn"),
                        ],
                    ),
                    Statement(
                        Effect=Allow,
                        Action=[s3.GetObject],
                        Resource=[Join("", [GetAtt(log_bucket, "Arn"), "/*"])],
                    ),
                ],
            ),
        ))

    bucket = template.add_resource(
        Bucket(
            "ContentBucket",
            LifecycleConfiguration=LifecycleConfiguration(Rules=[
                # not supported by CFN yet:
                # LifecycleRule(
                # Transitions=[
                # LifecycleRuleTransition(
                # StorageClass='INTELLIGENT_TIERING',
                # TransitionInDays=1,
                # ),
                # ],
                # Status="Enabled",
                # ),
                LifecycleRule(
                    AbortIncompleteMultipartUpload=
                    AbortIncompleteMultipartUpload(DaysAfterInitiation=7),
                    Status="Enabled",
                )
            ]),
            LoggingConfiguration=LoggingConfiguration(
                DestinationBucketName=Ref(log_bucket), LogFilePrefix="s3/"),
            BucketEncryption=BucketEncryption(
                ServerSideEncryptionConfiguration=[
                    ServerSideEncryptionRule(
                        ServerSideEncryptionByDefault=
                        ServerSideEncryptionByDefault(
                            # Origin Access Identities can't use KMS
                            SSEAlgorithm="AES256"))
                ]),
            OwnershipControls=OwnershipControls(Rules=[
                OwnershipControlsRule(ObjectOwnership="BucketOwnerPreferred")
            ], ),
            PublicAccessBlockConfiguration=PublicAccessBlockConfiguration(
                BlockPublicAcls=True,
                BlockPublicPolicy=True,
                IgnorePublicAcls=True,
                RestrictPublicBuckets=True,
            ),
        ))

    origin_access_identity = template.add_resource(
        CloudFrontOriginAccessIdentity(
            "CloudFrontIdentity",
            CloudFrontOriginAccessIdentityConfig=
            CloudFrontOriginAccessIdentityConfig(
                Comment=GetAtt(bucket, "Arn")),
        ))

    bucket_policy = template.add_resource(
        BucketPolicy(
            "ContentBucketPolicy",
            Bucket=Ref(bucket),
            PolicyDocument=PolicyDocument(
                Version="2012-10-17",
                Statement=[
                    Statement(
                        Effect=Allow,
                        Principal=Principal(
                            "CanonicalUser",
                            GetAtt(origin_access_identity,
                                   "S3CanonicalUserId"),
                        ),
                        Action=[s3.GetObject],
                        Resource=[Join("", [GetAtt(bucket, "Arn"), "/*"])],
                    ),
                ],
            ),
        ))

    # Not strictly necessary, as ACLs should take care of this access. However, CloudFront docs
    # state "In some circumstances [...] S3 resets permissions on the bucket to the default value",
    # and this allows logging to work without any ACLs in place.
    log_bucket_policy = template.add_resource(
        BucketPolicy(
            "LogBucketPolicy",
            Bucket=Ref(log_bucket),
            PolicyDocument=PolicyDocument(
                Version="2012-10-17",
                Statement=[
                    Statement(
                        Effect=Allow,
                        Principal=Principal("Service",
                                            "delivery.logs.amazonaws.com"),
                        Action=[s3.PutObject],
                        Resource=[
                            Join(
                                "/",
                                [GetAtt(log_bucket, "Arn"), "cloudfront", "*"])
                        ],
                    ),
                    Statement(
                        Effect=Allow,
                        Principal=Principal("Service",
                                            "delivery.logs.amazonaws.com"),
                        Action=[s3.ListBucket],
                        Resource=[Join("/", [GetAtt(log_bucket, "Arn")])],
                    ),
                    Statement(
                        Effect=Allow,
                        Principal=Principal("Service", "s3.amazonaws.com"),
                        Action=[s3.PutObject],
                        Resource=[
                            Join("/", [GetAtt(log_bucket, "Arn"), "s3", "*"])
                        ],
                    ),
                ],
            ),
        ))

    certificate_validator_dlq = template.add_resource(
        Queue(
            "CertificateValidatorDLQ",
            MessageRetentionPeriod=int(
                datetime.timedelta(days=14).total_seconds()),
            KmsMasterKeyId="alias/aws/sqs",
            Condition=should_create_certificate,
        ))

    certificate_validator_role = template.add_resource(
        Role(
            "CertificateValidatorRole",
            AssumeRolePolicyDocument=PolicyDocument(
                Version="2012-10-17",
                Statement=[
                    Statement(
                        Effect="Allow",
                        Principal=Principal("Service", "lambda.amazonaws.com"),
                        Action=[sts.AssumeRole],
                    )
                ],
            ),
            Policies=[
                PolicyProperty(
                    PolicyName="DLQPolicy",
                    PolicyDocument=PolicyDocument(
                        Version="2012-10-17",
                        Statement=[
                            Statement(
                                Effect=Allow,
                                Action=[sqs.SendMessage],
                                Resource=[
                                    GetAtt(certificate_validator_dlq, "Arn")
                                ],
                            )
                        ],
                    ),
                )
            ],
            # TODO scope down
            ManagedPolicyArns=[
                "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole",
                "arn:aws:iam::aws:policy/AmazonRoute53FullAccess",
                "arn:aws:iam::aws:policy/AWSCertificateManagerReadOnly",
            ],
            Condition=should_create_certificate,
        ))

    certificate_validator_function = template.add_resource(
        Function(
            "CertificateValidatorFunction",
            Runtime=PYTHON_RUNTIME,
            Handler="index.{}".format(certificate_validator.handler.__name__),
            Code=Code(ZipFile=inspect.getsource(certificate_validator)),
            MemorySize=256,
            Timeout=300,
            Role=GetAtt(certificate_validator_role, "Arn"),
            DeadLetterConfig=DeadLetterConfig(
                TargetArn=GetAtt(certificate_validator_dlq, "Arn")),
            Environment=Environment(
                Variables={
                    certificate_validator.EnvVars.HOSTED_ZONE_ID.name:
                    Ref(hosted_zone_id)
                }),
            Condition=should_create_certificate,
        ))

    certificate_validator_log_group = template.add_resource(
        LogGroup(
            "CertificateValidatorLogGroup",
            LogGroupName=Join(
                "", ["/aws/lambda/",
                     Ref(certificate_validator_function)]),
            RetentionInDays=If(retention_defined, Ref(log_retention_days),
                               NoValue),
            Condition=should_create_certificate,
        ))

    certificate_validator_rule = template.add_resource(
        Rule(
            "CertificateValidatorRule",
            EventPattern={
                "detail-type": ["AWS API Call via CloudTrail"],
                "detail": {
                    "eventSource": ["acm.amazonaws.com"],
                    "eventName": ["AddTagsToCertificate"],
                    "requestParameters": {
                        "tags": {
                            "key": [certificate_validator_function.title],
                            "value":
                            [GetAtt(certificate_validator_function, "Arn")],
                        }
                    },
                },
            },
            Targets=[
                Target(
                    Id="certificate-validator-lambda",
                    Arn=GetAtt(certificate_validator_function, "Arn"),
                )
            ],
            DependsOn=[certificate_validator_log_group],
            Condition=should_create_certificate,
        ))

    certificate_validator_permission = template.add_resource(
        Permission(
            "CertificateValidatorPermission",
            FunctionName=GetAtt(certificate_validator_function, "Arn"),
            Action="lambda:InvokeFunction",
            Principal="events.amazonaws.com",
            SourceArn=GetAtt(certificate_validator_rule, "Arn"),
            Condition=should_create_certificate,
        ))

    certificate = template.add_resource(
        Certificate(
            "Certificate",
            DomainName=Select(0, Ref(dns_names)),
            SubjectAlternativeNames=Ref(
                dns_names),  # duplicate first name works fine
            ValidationMethod="DNS",
            Tags=Tags(
                **{
                    certificate_validator_function.title:
                    GetAtt(certificate_validator_function, "Arn")
                }),
            DependsOn=[certificate_validator_permission],
            Condition=should_create_certificate,
        ))

    edge_hook_role = template.add_resource(
        Role(
            "EdgeHookRole",
            AssumeRolePolicyDocument=PolicyDocument(
                Version="2012-10-17",
                Statement=[
                    Statement(
                        Effect="Allow",
                        Principal=Principal(
                            "Service",
                            [
                                "lambda.amazonaws.com",
                                "edgelambda.amazonaws.com"
                            ],
                        ),
                        Action=[sts.AssumeRole],
                    )
                ],
            ),
        ))

    edge_hook_function = template.add_resource(
        Function(
            "EdgeHookFunction",
            Runtime=PYTHON_RUNTIME,
            Handler="index.handler",
            Code=Code(ZipFile=inspect.getsource(edge_hook)),
            MemorySize=128,
            Timeout=3,
            Role=GetAtt(edge_hook_role, "Arn"),
        ))
    edge_hook_function_hash = (hashlib.sha256(
        json.dumps(edge_hook_function.to_dict(),
                   sort_keys=True).encode("utf-8")).hexdigest()[:10].upper())

    edge_hook_version = template.add_resource(
        Version(
            "EdgeHookVersion" + edge_hook_function_hash,
            FunctionName=GetAtt(edge_hook_function, "Arn"),
        ))

    replica_log_group_name = Join(
        "/",
        [
            "/aws/lambda",
            Join(
                ".",
                [
                    FindInMap(partition_config, Partition, "PrimaryRegion"),
                    Ref(edge_hook_function),
                ],
            ),
        ],
    )

    edge_hook_role_policy = template.add_resource(
        PolicyType(
            "EdgeHookRolePolicy",
            PolicyName="write-logs",
            PolicyDocument=PolicyDocument(
                Version="2012-10-17",
                Statement=[
                    Statement(
                        Effect=Allow,
                        Action=[logs.CreateLogStream, logs.PutLogEvents],
                        Resource=[
                            Join(
                                ":",
                                [
                                    "arn",
                                    Partition,
                                    "logs",
                                    "*",
                                    AccountId,
                                    "log-group",
                                    replica_log_group_name,
                                    "log-stream",
                                    "*",
                                ],
                            ),
                        ],
                    ),
                ],
            ),
            Roles=[Ref(edge_hook_role)],
        ))

    stack_set_administration_role = template.add_resource(
        Role(
            "StackSetAdministrationRole",
            AssumeRolePolicyDocument=PolicyDocument(
                Version="2012-10-17",
                Statement=[
                    Statement(
                        Effect=Allow,
                        Principal=Principal("Service",
                                            "cloudformation.amazonaws.com"),
                        Action=[sts.AssumeRole],
                    ),
                ],
            ),
        ))

    stack_set_execution_role = template.add_resource(
        Role(
            "StackSetExecutionRole",
            AssumeRolePolicyDocument=PolicyDocument(
                Version="2012-10-17",
                Statement=[
                    Statement(
                        Effect=Allow,
                        Principal=Principal(
                            "AWS", GetAtt(stack_set_administration_role,
                                          "Arn")),
                        Action=[sts.AssumeRole],
                    ),
                ],
            ),
            Policies=[
                PolicyProperty(
                    PolicyName="create-stackset-instances",
                    PolicyDocument=PolicyDocument(
                        Version="2012-10-17",
                        Statement=[
                            Statement(
                                Effect=Allow,
                                Action=[
                                    cloudformation.DescribeStacks,
                                    logs.DescribeLogGroups,
                                ],
                                Resource=["*"],
                            ),
                            # stack instances communicate with the CFN service via SNS
                            Statement(
                                Effect=Allow,
                                Action=[sns.Publish],
                                NotResource=[
                                    Join(
                                        ":",
                                        [
                                            "arn", Partition, "sns", "*",
                                            AccountId, "*"
                                        ],
                                    )
                                ],
                            ),
                            Statement(
                                Effect=Allow,
                                Action=[
                                    logs.CreateLogGroup,
                                    logs.DeleteLogGroup,
                                    logs.PutRetentionPolicy,
                                    logs.DeleteRetentionPolicy,
                                ],
                                Resource=[
                                    Join(
                                        ":",
                                        [
                                            "arn",
                                            Partition,
                                            "logs",
                                            "*",
                                            AccountId,
                                            "log-group",
                                            replica_log_group_name,
                                            "log-stream",
                                            "",
                                        ],
                                    ),
                                ],
                            ),
                            Statement(
                                Effect=Allow,
                                Action=[
                                    cloudformation.CreateStack,
                                    cloudformation.DeleteStack,
                                    cloudformation.UpdateStack,
                                ],
                                Resource=[
                                    Join(
                                        ":",
                                        [
                                            "arn",
                                            Partition,
                                            "cloudformation",
                                            "*",
                                            AccountId,
                                            Join(
                                                "/",
                                                [
                                                    "stack",
                                                    Join(
                                                        "-",
                                                        [
                                                            "StackSet",
                                                            StackName, "*"
                                                        ],
                                                    ),
                                                ],
                                            ),
                                        ],
                                    )
                                ],
                            ),
                        ],
                    ),
                ),
            ],
        ))

    stack_set_administration_role_policy = template.add_resource(
        PolicyType(
            "StackSetAdministrationRolePolicy",
            PolicyName="assume-execution-role",
            PolicyDocument=PolicyDocument(
                Version="2012-10-17",
                Statement=[
                    Statement(
                        Effect=Allow,
                        Action=[sts.AssumeRole],
                        Resource=[GetAtt(stack_set_execution_role, "Arn")],
                    ),
                ],
            ),
            Roles=[Ref(stack_set_administration_role)],
        ))

    edge_log_groups = template.add_resource(
        StackSet(
            "EdgeLambdaLogGroupStackSet",
            AdministrationRoleARN=GetAtt(stack_set_administration_role, "Arn"),
            ExecutionRoleName=Ref(stack_set_execution_role),
            StackSetName=Join("-", [StackName, "EdgeLambdaLogGroup"]),
            PermissionModel="SELF_MANAGED",
            Description="Multi-region log groups for Lambda@Edge replicas",
            Parameters=[
                StackSetParameter(
                    ParameterKey="LogGroupName",
                    ParameterValue=replica_log_group_name,
                ),
                StackSetParameter(
                    ParameterKey="LogRetentionDays",
                    ParameterValue=Ref(log_retention_days),
                ),
            ],
            OperationPreferences=OperationPreferences(
                FailureToleranceCount=0,
                MaxConcurrentPercentage=100,
            ),
            StackInstancesGroup=[
                StackInstances(
                    DeploymentTargets=DeploymentTargets(Accounts=[AccountId]),
                    Regions=FindInMap(partition_config, Partition,
                                      "DefaultRegions"),
                )
            ],
            TemplateBody=create_log_group_template().to_json(indent=None),
            DependsOn=[stack_set_administration_role_policy],
        ))

    price_class_distribution = template.add_resource(
        Distribution(
            "PriceClassDistribution",
            DistributionConfig=DistributionConfig(
                Comment="Dummy distribution used for price class hack",
                DefaultCacheBehavior=DefaultCacheBehavior(
                    TargetOriginId="default",
                    ViewerProtocolPolicy="allow-all",
                    ForwardedValues=ForwardedValues(QueryString=False),
                ),
                Enabled=True,
                Origins=[
                    Origin(Id="default",
                           DomainName=GetAtt(bucket, "DomainName"))
                ],
                IPV6Enabled=True,
                ViewerCertificate=ViewerCertificate(
                    CloudFrontDefaultCertificate=True),
                PriceClass="PriceClass_All",
            ),
            Condition=using_price_class_hack,
        ))

    distribution = template.add_resource(
        Distribution(
            "ContentDistribution",
            DistributionConfig=DistributionConfig(
                Enabled=True,
                Aliases=If(using_dns_names, Ref(dns_names), NoValue),
                Logging=Logging(Bucket=GetAtt(log_bucket, "DomainName"),
                                Prefix="cloudfront/"),
                DefaultRootObject="index.html",
                Origins=[
                    Origin(
                        Id="default",
                        DomainName=GetAtt(bucket, "DomainName"),
                        S3OriginConfig=S3OriginConfig(
                            OriginAccessIdentity=Join(
                                "",
                                [
                                    "origin-access-identity/cloudfront/",
                                    Ref(origin_access_identity),
                                ],
                            )),
                    )
                ],
                DefaultCacheBehavior=DefaultCacheBehavior(
                    TargetOriginId="default",
                    Compress=True,
                    ForwardedValues=ForwardedValues(QueryString=False),
                    ViewerProtocolPolicy="redirect-to-https",
                    DefaultTTL=Ref(default_ttl_seconds),
                    LambdaFunctionAssociations=[
                        LambdaFunctionAssociation(
                            EventType="origin-request",
                            LambdaFunctionARN=Ref(edge_hook_version),
                        )
                    ],
                ),
                HttpVersion="http2",
                IPV6Enabled=True,
                ViewerCertificate=ViewerCertificate(
                    AcmCertificateArn=If(
                        using_acm_certificate,
                        Ref(acm_certificate_arn),
                        If(using_hosted_zone, Ref(certificate), NoValue),
                    ),
                    SslSupportMethod=If(using_certificate, "sni-only",
                                        NoValue),
                    CloudFrontDefaultCertificate=If(using_certificate, NoValue,
                                                    True),
                    MinimumProtocolVersion=Ref(tls_protocol_version),
                ),
                PriceClass=If(using_price_class_hack, "PriceClass_100",
                              "PriceClass_All"),
            ),
            DependsOn=[
                bucket_policy,
                log_ingester_policy,
                edge_log_groups,
                precondition_region_is_primary,
            ],
        ))

    distribution_log_group = template.add_resource(
        LogGroup(
            "DistributionLogGroup",
            LogGroupName=Join(
                "", ["/aws/cloudfront/", Ref(distribution)]),
            RetentionInDays=If(retention_defined, Ref(log_retention_days),
                               NoValue),
        ))

    bucket_log_group = template.add_resource(
        LogGroup(
            "BucketLogGroup",
            LogGroupName=Join("", ["/aws/s3/", Ref(bucket)]),
            RetentionInDays=If(retention_defined, Ref(log_retention_days),
                               NoValue),
        ))

    template.add_output(Output("DistributionId", Value=Ref(distribution)))

    template.add_output(
        Output("DistributionDomain", Value=GetAtt(distribution, "DomainName")))

    template.add_output(
        Output(
            "DistributionDnsTarget",
            Value=If(
                using_price_class_hack,
                GetAtt(price_class_distribution, "DomainName"),
                GetAtt(distribution, "DomainName"),
            ),
        ))

    template.add_output(
        Output(
            "DistributionUrl",
            Value=Join("",
                       ["https://",
                        GetAtt(distribution, "DomainName"), "/"]),
        ))

    template.add_output(Output("ContentBucketArn", Value=GetAtt(bucket,
                                                                "Arn")))

    return template
Beispiel #16
0
    template.add_condition(
        assets_create_certificate_condition,
        And(
            Not(Equals(Ref(assets_cloudfront_domain), "")),
            Equals(Ref(AWS_REGION), "us-east-1"),
            Equals(Ref(assets_certificate_arn), "")
        )
    )

    assets_certificate = template.add_resource(
        Certificate(
            'AssetsCertificate',
            Condition=assets_create_certificate_condition,
            DomainName=Ref(assets_cloudfront_domain),
            DomainValidationOptions=[
                DomainValidationOption(
                    DomainName=Ref(assets_cloudfront_domain),
                    ValidationDomain=Ref(assets_cloudfront_domain),
                ),
            ],
        )
    )

    # Create a CloudFront CDN distribution
    distribution = template.add_resource(
        Distribution(
            'AssetsDistribution',
            Condition=assets_use_cloudfront_condition,
            DistributionConfig=DistributionConfig(
                Aliases=If(assets_custom_domain_condition, [Ref(assets_cloudfront_domain)], Ref("AWS::NoValue")),
                # use the ACM certificate we created (if any), otherwise fall back to the manually-supplied
Beispiel #17
0
from troposphere import If, Ref
from troposphere.certificatemanager import Certificate, DomainValidationOption

from .domain import domain_name, domain_name_alternates, no_alt_domains
from .template import template

application = Ref(
    template.add_resource(
        Certificate(
            'Certificate',
            DomainName=domain_name,
            SubjectAlternativeNames=If(no_alt_domains, Ref("AWS::NoValue"),
                                       domain_name_alternates),
            DomainValidationOptions=[
                DomainValidationOption(
                    DomainName=domain_name,
                    ValidationDomain=domain_name,
                ),
            ],
        )))
Beispiel #18
0
    default_ttl = 86400,

    # If an alt_sub domain is not specified use empty string
    if domain_info['alt_sub'] != '':
        alternate_name = '{}.{}'.format(domain_info['alt_sub'], src_domain)
    else:
        alternate_name = ''

    # Provision certificate for CDN
    cdnCertificate = t.add_resource(
        Certificate('cdnCertificate{}'.format(src_domain.replace('.', '0')),
                    DomainName=cdn_domain,
                    DependsOn=redirectBucket,
                    SubjectAlternativeNames=[alternate_name],
                    DomainValidationOptions=[
                        DomainValidationOption(DomainName=cdn_domain,
                                               ValidationDomain=dns_domain)
                    ],
                    ValidationMethod='DNS',
                    Tags=DefaultTags +
                    Tags(Name='{}-{}'.format(env_l, app_group_l))))

    # Provision the CDN Origin
    cdnOrigin = cf.Origin(Id='{}-{}-{}'.format(env_l, app_group_l, src_domain),
                          DomainName=Select(
                              1,
                              Split('//', GetAtt(redirectBucket,
                                                 'WebsiteURL'))),
                          CustomOriginConfig=cf.CustomOriginConfig(
                              HTTPPort=80,
                              HTTPSPort=443,
Beispiel #19
0
            'VIDEO_TABLE': Ref(video_table),
        }
    ),
))

template.add_resource(LogGroup(
    "AllVideosFunctionLogGroup",
    LogGroupName=Join('/', ['/aws/lambda', Ref(all_videos_function)]),
    RetentionInDays=7,
))

api_certificate = template.add_resource(Certificate(
    "ApiCertificate",
    DomainName=Ref(domain_name),
    DomainValidationOptions=[DomainValidationOption(
        DomainName=Ref(domain_name),
        ValidationDomain=ImportValue(Join('-', [Ref(dns_stack), 'HostedZoneName'])),
    )],
    ValidationMethod='DNS',
))

api_domain_name = template.add_resource(DomainName(
    'ApiDomainName',
    RegionalCertificateArn=Ref(api_certificate),
    DomainName=Ref(domain_name),
    EndpointConfiguration=EndpointConfiguration(
        Types=['REGIONAL'],
    ),
))

template.add_resource(BasePathMapping(