Esempio n. 1
0
    def __init__(self, scope: core.Construct, construct_id: str, env, vars,
                 **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        rt53_client = boto3.client('route53')

        # get domain name from vars.py file
        domain_name = vars['domain_name']

        # get hosted zone ID
        # change to use pagination if over 100 zones
        response = rt53_client.list_hosted_zones()
        h_zones = response['HostedZones']
        for h_zone in h_zones:
            name = h_zone['Name']
            if name[0:-1] == domain_name:
                h_zone_id = h_zone['Id'].split("/")[2]
                #print(h_zone_id)

        # create an IHostedZone object
        self._hosted_zone = rt53.HostedZone.from_hosted_zone_attributes(
            self, "fhzi", hosted_zone_id=h_zone_id, zone_name=domain_name)

        # Create the ACM certificate, this will do DNS validation automagically
        self._acm_cert = acm.Certificate(
            self,
            "CF SSL Cert",
            domain_name=vars['cdn_domain'],
            validation=acm.CertificateValidation.from_dns(self._hosted_zone))
Esempio n. 2
0
    def __init__(self, scope: core.Construct, id: str, bucket_name: str,
                 cf_id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        # The code that defines your stack goes here
        bucket = s3.Bucket(self,
                           id=id,
                           bucket_name=bucket_name,
                           access_control=s3.BucketAccessControl.PUBLIC_READ,
                           website_index_document="index.html")
        bucket.grant_public_access()
        cert = acm.Certificate(self,
                               "Cert",
                               domain_name=bucket_name,
                               validation=acm.CertificateValidation.from_dns())

        cf.CloudFrontWebDistribution(
            self,
            id=cf_id,
            price_class=cf.PriceClass.PRICE_CLASS_200,
            origin_configs=[
                cf.SourceConfiguration(
                    behaviors=[cf.Behavior(is_default_behavior=True)],
                    s3_origin_source=cf.S3OriginConfig(
                        s3_bucket_source=bucket))
            ],
            alias_configuration=cf.AliasConfiguration(
                names=[bucket_name], acm_cert_ref=cert.certificate_arn))
Esempio n. 3
0
    def __init__(self, scope: core.Construct, id: str, domain_name: str,
                 **kwargs):
        super().__init__(scope, id, **kwargs)

        self._certificate = acm.Certificate(
            self,
            "Certificate",
            domain_name=domain_name,
            validation=acm.CertificateValidation.from_dns())
Esempio n. 4
0
    def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        certificate = cm.Certificate(
            self,
            "certs",
            domain_name=f"{stack_vars.bucket_name}",
            subject_alternative_names=[f"www.{stack_vars.bucket_name}"],
            validation_method=cm.ValidationMethod.DNS)
def generate_acm_certificate(scope, hosted_zone):
    certificate = certificatemanager.Certificate(
        scope=scope,
        id="JVSANTOSTier1ACMCertificate",
        domain_name="jvsantos-tier1.apperdevops.com",
        subject_alternative_names=["*.jvsantos-tier1.apperdevops.com"],
        validation=certificatemanager.CertificateValidation.from_dns(
            hosted_zone),
    )
    return certificate
Esempio n. 6
0
    def __init__(
            self,
            scope: core.Construct,
            id: str,  # pylint: disable=redefined-builtin
            lambda_notifications: aws_lambda.IFunction,
            social_log_group: aws_logs.ILogGroup,
            pagespeed_table: aws_dynamodb.ITable,
            **kwargs) -> None:

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

        api_lambda = get_lambda(
            self,
            id,
            code='lib/stacks/{id}/{id}'.format(id=id),
            handler='main.handler',
            environment={
                'CORS_ALLOW_ORIGIN': env['CORS_ALLOW_ORIGIN'],
                'PUSHOVER_TOKEN': env['PUSHOVER_TOKEN'],
                'PUSHOVER_USERKEY': env['PUSHOVER_USERKEY'],
                'LAMBDA_FUNCTIONS_LOG_LEVEL': 'INFO',
                'LAMBDA_NOTIFICATIONS': lambda_notifications.function_name,
                'PAGESPEED_TABLE': pagespeed_table.table_name,
                'REPORT_LOG_GROUP_NAME': social_log_group.log_group_name,
            },
        )
        lambda_notifications.grant_invoke(api_lambda)
        social_log_group.grant(api_lambda, "logs:GetLogEvents",
                               "logs:DescribeLogStreams")
        pagespeed_table.grant_read_data(api_lambda)

        cert = aws_certificatemanager.Certificate(
            self,
            '{}-certificate'.format(id),
            domain_name=env['API_DOMAIN'],
        )

        domain = aws_apigateway.DomainNameOptions(
            certificate=cert,
            domain_name=env['API_DOMAIN'],
        )

        cors = aws_apigateway.CorsOptions(
            allow_methods=['POST'],
            allow_origins=[env['CORS_ALLOW_ORIGIN']]
            if "CORS_ALLOW_ORIGIN" in env else aws_apigateway.Cors.ALL_ORIGINS)

        aws_apigateway.LambdaRestApi(
            self,
            '%s-gateway' % id,
            handler=api_lambda,
            domain_name=domain,
            default_cors_preflight_options=cors,
        )
Esempio n. 7
0
 def __init__(self, scope: core.Construct, construct_id: str,
              **kwargs) -> None:
     super().__init__(scope, construct_id, **kwargs)
     # Define ACM Certs
     for cdk_id, (domain_name, validation_method) in ACM_Certs_List.items():
         aws_certificatemanager.Certificate(
             self,
             cdk_id,
             domain_name=domain_name,
             validation_method=validation_method,
         )
 def __create_ssl_certificate(
     self, route_53_hosted_zone: aws_route53.HostedZone, domain_name: str,
     alternative_domain_names: Optional[List[str]]
 ) -> aws_certificatemanager.Certificate:
     return aws_certificatemanager.Certificate(
         self,
         'SSLCertificate',
         domain_name=domain_name,
         validation=CertificateValidation.from_dns(
             hosted_zone=route_53_hosted_zone),
         subject_alternative_names=alternative_domain_names)
Esempio n. 9
0
    def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)
        self._domain_name = "sadevs.app"
        self._hosted_zone = route53.PublicHostedZone(
            self, "HostedZone", zone_name=self._domain_name)

        self._certificate = certificate_manager.Certificate(
            self,
            "sadevs-apps-cert",
            domain_name=self._domain_name,
            subject_alternative_names=[f"*.{self._domain_name}"],
            validation_method=certificate_manager.ValidationMethod.DNS,
        )
Esempio n. 10
0
 def __create_certificate(self, hosted_zone):
     if self.__domain_certificate_arn:
         # If certificate arn is provided, import the certificate
         self.certificate = acm.Certificate.from_certificate_arn(
             self,
             "site_certificate",
             certificate_arn=self.__domain_certificate_arn,
         )
     else:
         # If certificate arn is not provided, create a new one
         self.certificate = acm.Certificate(
             self,
             "site_certificate",
             domain_name=self.__site_domain_name,
             validation=acm.CertificateValidation.from_dns(hosted_zone),
         )
    def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        my_lambda = aws_lambda.Function(
            self,
            environ['CDK_APP_NAME'],
            runtime=aws_lambda.Runtime.PYTHON_3_8,
            code=aws_lambda.Code.asset('lambda'),
            handler='contact_us.handler',
            environment={
                'CORS_ALLOW_ORIGIN': environ.get('CORS_ALLOW_ORIGIN', '*'),
                'PUSHOVER_API_ENDPOINT': environ['PUSHOVER_API_ENDPOINT'],
                'PUSHOVER_TOKEN': environ['PUSHOVER_TOKEN'],
                'PUSHOVER_USERKEY': environ['PUSHOVER_USERKEY'],
            },
            log_retention=aws_logs.RetentionDays.ONE_WEEK,
        )

        cert = aws_certificatemanager.Certificate(
            self,
            '{}-certificate'.format(environ['CDK_APP_NAME']),
            domain_name=environ['CDK_BASE_DOMAIN'],
        )

        domain = aws_apigateway.DomainNameOptions(
            certificate=cert,
            domain_name=environ['CDK_BASE_DOMAIN'],
        )

        cors = aws_apigateway.CorsOptions(
            allow_methods=["POST"],
            allow_origins=[environ['CORS_ALLOW_ORIGIN']]
            if environ.get('CORS_ALLOW_ORIGIN') else
            aws_apigateway.Cors.ALL_ORIGINS,
        )

        aws_apigateway.LambdaRestApi(
            self,
            '{}-gateway'.format(environ['CDK_APP_NAME']),
            handler=my_lambda,
            domain_name=domain,
            default_cors_preflight_options=cors,
        )
Esempio n. 12
0
    def __init__(self, scope: core.Construct, id: str, sub_domain: str,
                 domain: str, **kwargs) -> None:
        """
        CertificateStack creates the CloudFormation Stack that provisions the SSL Certificate that the CloudFront Distributions use for HTTPS traffic.

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

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

        # Certificate covers the domain, acg-covid-challenge.my-domain.com
        certificate = cm.Certificate(self,
                                     "MyCertificate",
                                     domain_name=f"{sub_domain}.{domain}",
                                     validation_method=cm.ValidationMethod.DNS)

        core.CfnOutput(self,
                       "certificatearn",
                       value=certificate.certificate_arn)
    def __init__(self, scope: core.Construct, id: str, domain: str,
                 **kwargs) -> None:
        """
        CertificateStack creates the CloudFormation Stack that provisions the SSL Certificate that the CloudFront Distributions use for HTTPS traffic.

        arguments:
        domain -- custom domain name owned by user, e.g. my-domain.com        
        """

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

        # Certificate covers three domains, prod.my-domain.com, dev.my-domain.com, stg.my-domain.com
        # To use alternative sub-domains, the domain_name and subject_alternative_names keyword arguments must be changed
        certificate = cm.Certificate(
            self,
            "MyCertificate",
            domain_name=f"prod.{domain}",
            subject_alternative_names=[f"dev.{domain}", f"stg.{domain}"],
            validation_method=cm.ValidationMethod.DNS)

        core.CfnOutput(self,
                       "certificatearn",
                       value=certificate.certificate_arn)
Esempio n. 14
0
    def __init__(self, scope: cdk.Construct, construct_id: str,
                 **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)
        environment = self.node.try_get_context('environment')
        server_domain = self.node.try_get_context('server_domain')
        hosted_zone_id = self.node.try_get_context('hosted_zone_id')

        if environment == 'prod':
            self.domain_name = f'start.{server_domain}'
        else:
            self.domain_name = f'start.{environment}.{server_domain}'

        hosted_zone = r53.HostedZone.from_hosted_zone_attributes(
            self,
            'Zone',
            hosted_zone_id=hosted_zone_id,
            zone_name=server_domain)
        certificate = acm.Certificate(
            self,
            'StartCert',
            domain_name=self.domain_name,
            validation=acm.CertificateValidation.from_dns(
                hosted_zone=hosted_zone))
        self.rest_api = apigw.RestApi(
            self,
            'api',
            domain_name=apigw.DomainNameOptions(certificate=certificate,
                                                domain_name=self.domain_name),
            deploy_options=apigw.StageOptions(stage_name=environment))
        arecord = r53.ARecord(
            self,
            'StartARecord',
            zone=hosted_zone,
            record_name=self.domain_name,
            target=r53.RecordTarget(
                alias_target=r53_targets.ApiGateway(self.rest_api)))
        cdk.CfnOutput(self, 'DNSName', value=arecord.domain_name)
Esempio n. 15
0
    def __init__(
        self,
        scope: cdk.Construct,
        id: str,
        consoleme_alb: lb.ApplicationLoadBalancer,
        **kwargs
    ) -> None:
        super().__init__(scope, id, **kwargs)

        hosted_zone = route53.PublicHostedZone.from_hosted_zone_attributes(
            self,
            "HostedZone",
            hosted_zone_id=HOSTED_ZONE_ID,
            zone_name=HOSTED_ZONE_NAME,
        )

        route53_record = route53.ARecord(
            self,
            "LBRecord",
            zone=hosted_zone,
            record_name=APPLICATION_PREFIX,
            target=route53.RecordTarget(
                alias_target=(route53_targets.LoadBalancerTarget(consoleme_alb))
            ),
        )

        verify_ses_identity = cr.AwsCustomResource(
            self,
            "VerifySESIdentityResource",
            policy=cr.AwsCustomResourcePolicy.from_statements(
                statements=[
                    iam.PolicyStatement(
                        effect=iam.Effect.ALLOW,
                        actions=["ses:VerifyDomainIdentity", "ses:DeleteIdentity"],
                        resources=["*"],
                    )
                ]
            ),
            on_create=cr.AwsSdkCall(
                service="SES",
                action="verifyDomainIdentity",
                parameters={"Domain": route53_record.domain_name},
                physical_resource_id=cr.PhysicalResourceId.from_response(
                    "VerificationToken"
                ),
            ),
            on_delete=cr.AwsSdkCall(
                service="SES",
                action="deleteIdentity",
                parameters={"Identity": route53_record.domain_name},
            ),
            install_latest_aws_sdk=True,
            log_retention=logs.RetentionDays.ONE_WEEK,
        )

        add_ses_dkim = cr.AwsCustomResource(
            self,
            "VerifySESDKIMResource",
            policy=cr.AwsCustomResourcePolicy.from_statements(
                statements=[
                    iam.PolicyStatement(
                        effect=iam.Effect.ALLOW,
                        actions=["ses:VerifyDomainDkim"],
                        resources=["*"],
                    )
                ]
            ),
            on_create=cr.AwsSdkCall(
                service="SES",
                action="verifyDomainDkim",
                parameters={"Domain": route53_record.domain_name},
                physical_resource_id=cr.PhysicalResourceId.of(
                    HOSTED_ZONE_ID + "VerifyDomainDKIM"
                ),
            ),
            install_latest_aws_sdk=True,
            log_retention=logs.RetentionDays.ONE_WEEK,
        )

        add_ses_dkim.node.add_dependency(verify_ses_identity)

        certificate = acm.Certificate(
            self,
            "Certificate",
            domain_name="*." + hosted_zone.zone_name,
            validation=acm.CertificateValidation.from_dns(hosted_zone=hosted_zone),
        )

        self.hosted_zone = hosted_zone
        self.certificate = certificate
        self.route53_record = route53_record
Esempio n. 16
0
    def __init__(self,
                 scope: core.Construct,
                 construct_id: str,
                 cdk_env_='',
                 **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        this_dir = path.dirname(__file__)

        # Dynamo DB Tables
        dynamo_names_table = dynamodb.Table(
            self,
            'Names',
            partition_key=dynamodb.Attribute(
                name='name', type=dynamodb.AttributeType.STRING),
            sort_key=dynamodb.Attribute(name='gender',
                                        type=dynamodb.AttributeType.STRING),
            billing_mode=dynamodb.BillingMode.PAY_PER_REQUEST)
        dynamo_names_table.add_global_secondary_index(
            partition_key=dynamodb.Attribute(
                name='gender', type=dynamodb.AttributeType.STRING),
            sort_key=dynamodb.Attribute(name='uuid',
                                        type=dynamodb.AttributeType.STRING),
            index_name='bn_uuid_sort')

        # Lambda Layers
        lambda_layer_requests = lmb.LayerVersion(
            self,
            'Layer-Requests',
            code=lmb.Code.from_asset(
                path.join(this_dir, 'lambda/layers/requests.zip')),
            compatible_runtimes=[lmb.Runtime.PYTHON_3_8],
        )
        lambda_layer_simplejson = lmb.LayerVersion(
            self,
            'Layer-SimpleJSON',
            code=lmb.Code.from_asset(
                path.join(this_dir, 'lambda/layers/simplejson.zip')),
            compatible_runtimes=[lmb.Runtime.PYTHON_3_8],
        )
        lambda_layer_jinja2 = lmb.LayerVersion(
            self,
            'Layer-Jinja2',
            code=lmb.Code.from_asset(
                path.join(this_dir, 'lambda/layers/jinja2.zip')),
            compatible_runtimes=[lmb.Runtime.PYTHON_3_8],
        )

        ## Lambda - API Handler
        lambda_api_handler = lmb.Function(
            self,
            'API-Handler',
            timeout=core.Duration.seconds(360),
            memory_size=512,
            runtime=lmb.Runtime.PYTHON_3_8,
            handler='api_handler.handler',
            layers=[lambda_layer_simplejson, lambda_layer_jinja2],
            code=lmb.Code.from_asset(path.join(this_dir,
                                               'lambda/api_handler')),
            environment={'DYNAMO_DB_NAMES': dynamo_names_table.table_name})
        ### Grants
        dynamo_names_table.grant_read_write_data(lambda_api_handler)

        # APIGW
        ## Pull domain values from parameter store
        parameter_store_record_name = ssm.StringParameter.value_for_string_parameter(
            self, f'/babynames/{cdk_env_}/record_name')
        parameter_store_domain_name = ssm.StringParameter.value_for_string_parameter(
            self, f'/babynames/{cdk_env_}/domain_name')
        parameter_store_zone_id = ssm.StringParameter.value_for_string_parameter(
            self, f'/babynames/{cdk_env_}/zone_id')

        ## Import R53 Zone
        r53_zone = route53.HostedZone.from_hosted_zone_attributes(
            self,
            "R53Zone",
            zone_name=parameter_store_domain_name,
            hosted_zone_id=parameter_store_zone_id)

        ## ACM Certificate
        acm_certificate = acm.Certificate(
            self,
            "BabyNamesCertificate",
            domain_name=parameter_store_record_name,
            validation=acm.CertificateValidation.from_dns(r53_zone))

        ## APIGW Custom Domain
        apigw_baby_names_domain_name = apigw2.DomainName(
            self,
            "BabyNamesDomain",
            domain_name=parameter_store_record_name,
            certificate=acm.Certificate.from_certificate_arn(
                self, "BabyNamesCert", acm_certificate.certificate_arn))

        ## Set R53 Records
        r53_alias_target_baby_names_apigw = r53targets.ApiGatewayv2Domain(
            apigw_baby_names_domain_name)
        route53.ARecord(self,
                        "BabyNamesARecord",
                        record_name='babynames',
                        zone=r53_zone,
                        target=route53.RecordTarget.from_alias(
                            r53_alias_target_baby_names_apigw))

        ## Instantiate APIGW
        apigw_baby_names = apigw2.HttpApi(
            self,
            'BabyNames-APIGW-Http',
            default_domain_mapping=(apigw2.DefaultDomainMappingOptions(
                domain_name=apigw_baby_names_domain_name)))

        ## APIGW Integrations
        ## Lambda Integrations
        lambda_int_lambda_api_handler = apigw2int.LambdaProxyIntegration(
            handler=lambda_api_handler)

        apigw_baby_names.add_routes(path='/{name}/{gender}',
                                    methods=[apigw2.HttpMethod.GET],
                                    integration=lambda_int_lambda_api_handler)

        apigw_baby_names.add_routes(path='/{proxy+}',
                                    methods=[apigw2.HttpMethod.GET],
                                    integration=lambda_int_lambda_api_handler)
Esempio n. 17
0
    def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        # Define S3 bucket that will host site assets
        website_bucket = s3.Bucket(
            self,
            'parthrparikh-com-assets-bucket',
            website_index_document='index.html',
            block_public_access=s3.BlockPublicAccess.BLOCK_ALL,
        )
        # Deny non-SSL traffic
        website_bucket.add_to_resource_policy(
            iam.PolicyStatement(
                effect=iam.Effect.DENY,
                actions=["s3:*"],
                resources=[website_bucket.bucket_arn],
                conditions={'Bool': {
                    'aws:SecureTransport': False,
                }},
                principals=[iam.AnyPrincipal()],
            ))
        s3_deploy.BucketDeployment(
            self,
            'parthrparikh-com-deploy-website',
            sources=[s3_deploy.Source.asset('../website/')],
            destination_bucket=website_bucket,
        )

        # Define certificate for parthrparikh.com
        cert = acm.Certificate(self,
                               'parthrparikh-com-cert',
                               domain_name='parthrparikh.com',
                               subject_alternative_names=[
                                   'www.parthrparikh.com',
                               ])

        # Define CloudFront distribution
        origin_access_identity = cf.OriginAccessIdentity(
            self,
            'OriginAccessIdentity',
            comment='Personal website (parthrparikh.com) OAI to reach bucket',
        )
        website_bucket.grant_read(origin_access_identity)
        distro = cf.CloudFrontWebDistribution(
            self,
            'parthrparikh-com-distribution',
            origin_configs=[
                cf.SourceConfiguration(
                    s3_origin_source=cf.S3OriginConfig(
                        s3_bucket_source=website_bucket,
                        origin_access_identity=origin_access_identity),
                    behaviors=[
                        cf.Behavior(
                            is_default_behavior=True,
                            default_ttl=core.Duration.minutes(10),
                            max_ttl=core.Duration.hours(1),
                        )
                    ],
                ),
            ],
            viewer_certificate=cf.ViewerCertificate.from_acm_certificate(
                certificate=cert,
                aliases=[
                    'parthrparikh.com',
                    'www.parthrparikh.com',
                ]),
            viewer_protocol_policy=cf.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
        )
Esempio n. 18
0
    def __init__(self, scope: cdk.Construct, construct_id: str,
                 **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)
        '''
        create a vpc for the splunk environment, cdk will take care of subnetting
        additionally create a sg for the splunk instance that only accepts request from the alb
        the redirect compensates for splunk trying to redirect to http on every response
        '''
        vpc = ec2.Vpc(self, 'vpc', max_azs=2)
        instance_type = ec2.InstanceType('t2.micro')
        ami = ec2.LookupMachineImage(name='splunk_AMI_8.2.0_2021*')
        splunk_sg = ec2.SecurityGroup(self, 'splunk_sg', vpc=vpc)
        splunk_instance = ec2.Instance(self,
                                       'splunk',
                                       instance_type=instance_type,
                                       machine_image=ami,
                                       vpc=vpc,
                                       security_group=splunk_sg)
        alb = lb.ApplicationLoadBalancer(self,
                                         'alb',
                                         vpc=vpc,
                                         internet_facing=True)
        splunk_sg.connections.allow_from(alb, ec2.Port.tcp(8000))
        splunk_sg.connections.allow_from(alb, ec2.Port.tcp(8088))
        alb.add_redirect()

        # import existing hosted zone and create certificate using dns based validation
        my_hosted_zone = route53.HostedZone.from_lookup(
            self, 'importedzone', domain_name='vosskuhler.com')
        certificate = acm.Certificate(
            self,
            "Certificate",
            domain_name="splunk.vosskuhler.com",
            validation=acm.CertificateValidation.from_dns(my_hosted_zone))
        '''
        configure listeners on the alb, by default splunk uses http on 8000 and https on 8088
        ssl offloading will take care off the TLS certificate and allows us to not have to reconfigure 
        splunk to utilize https on port 8000. To check HEC health you can visit <url>:8088/services/collector/health/1.0
        '''
        listener = alb.add_listener(
            "Listener",
            certificates=[lb.ListenerCertificate(certificate.certificate_arn)],
            port=443,
            open=True)
        listener.add_targets("splunk",
                             port=8000,
                             targets=[lbt.InstanceTarget(splunk_instance)])
        listener_hec = alb.add_listener(
            "Listener_hec",
            certificates=[lb.ListenerCertificate(certificate.certificate_arn)],
            port=8088,
            open=True,
            protocol=lb.ApplicationProtocol('HTTPS'))
        listener_hec.add_targets("splunk_hec",
                                 port=8088,
                                 protocol=lb.ApplicationProtocol('HTTPS'),
                                 targets=[lbt.InstanceTarget(splunk_instance)])

        # configure dns to forward traffic to the alb
        route53.ARecord(self,
                        "cnamerecord",
                        zone=my_hosted_zone,
                        target=route53.RecordTarget.from_alias(
                            alias.LoadBalancerTarget(alb)),
                        record_name='splunk.vosskuhler.com')
Esempio n. 19
0
    def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        # store
        dynamodb_table = dynamodb.Table(
            self,
            'dynamodb_table',
            table_name=f'{PROJECT}_{STAGE}',
            partition_key=dynamodb.Attribute(
                name='date', type=dynamodb.AttributeType.STRING),
            billing_mode=dynamodb.BillingMode.PAY_PER_REQUEST,
            point_in_time_recovery=False,
            removal_policy=core.RemovalPolicy.DESTROY,
            server_side_encryption=True,
        )

        # public api
        public_api = appsync.CfnGraphQLApi(
            self,
            'public_api',
            name=f'{PROJECT}_{STAGE}',
            authentication_type='API_KEY',
        )

        now = time.localtime()
        epoch = time.mktime(now)
        public_api_key = appsync.CfnApiKey(
            self,
            'public_api_key',
            api_id=public_api.attr_api_id,
            expires=epoch + core.Duration.days(90).to_seconds(),
        )

        with open('schema.gql', mode='r') as f:
            graphql_schema = f.read()

            appsync.CfnGraphQLSchema(self,
                                     'public_api_schema',
                                     api_id=public_api.attr_api_id,
                                     definition=graphql_schema)

        public_api_role = iam.Role(
            self,
            'public_api_role',
            assumed_by=iam.ServicePrincipal('appsync.amazonaws.com'),
            managed_policies=[
                iam.ManagedPolicy.from_aws_managed_policy_name(
                    'AmazonDynamoDBFullAccess')
            ],
        )

        public_api_datasource = appsync.CfnDataSource(
            self,
            'public_api_datasource',
            api_id=public_api.attr_api_id,
            name=f'{PROJECT}_{STAGE}_dynamodb',
            type='AMAZON_DYNAMODB',
            dynamo_db_config={
                'awsRegion': 'us-east-1',
                'tableName': dynamodb_table.table_name,
            },
            service_role_arn=public_api_role.role_arn,
        )

        with open('mapping_templates/get_holiday.json', mode='r') as f:
            get_holiday_json = f.read()

            appsync.CfnResolver(
                self,
                'public_api_resolver_get_holiday',
                api_id=public_api.attr_api_id,
                type_name='Query',
                field_name='getHoliday',
                data_source_name=public_api_datasource.attr_name,
                kind='UNIT',
                request_mapping_template=get_holiday_json,
                response_mapping_template='$util.toJson($context.result)',
            )

        with open('mapping_templates/list_holidays.json', mode='r') as f:
            list_holidays_json = f.read()

            appsync.CfnResolver(
                self,
                'public_api_resolver_list_holidays',
                api_id=public_api.attr_api_id,
                type_name='Query',
                field_name='listHolidays',
                data_source_name=public_api_datasource.attr_name,
                kind='UNIT',
                request_mapping_template=list_holidays_json,
                response_mapping_template='$util.toJson($context.result)',
            )

        # lambda source code upload to s3
        lambda_assets = s3_assets.Asset(self,
                                        'lambda_assets',
                                        path='./function/.artifact/')

        # update function
        func_api = lambda_.Function(
            self,
            f'{PROJECT}-{STAGE}-func',
            function_name=f'{PROJECT}-{STAGE}-func',
            code=lambda_.Code.from_bucket(bucket=lambda_assets.bucket,
                                          key=lambda_assets.s3_object_key),
            handler='app.handler',
            runtime=lambda_.Runtime.PYTHON_3_7,
            timeout=core.Duration.seconds(120),
            log_retention=logs.RetentionDays.SIX_MONTHS,
            memory_size=128,
            tracing=lambda_.Tracing.ACTIVE,
        )
        func_api.add_environment('TABLE_NAME', dynamodb_table.table_name)
        func_api.add_environment('CSV_URL', CSV_URL)
        func_api.add_to_role_policy(
            iam.PolicyStatement(
                actions=[
                    'dynamodb:Get*',
                    'dynamodb:Put*',
                    'dynamodb:Batch*',
                ],
                resources=[dynamodb_table.table_arn],
            ))

        # schedule execute
        events.Rule(
            self,
            f'{PROJECT}-{STAGE}-schedule',
            enabled=True,
            schedule=events.Schedule.rate(core.Duration.days(10)),
            targets=[events_targets.LambdaFunction(func_api)],
        )

        # lambda@edge
        func_lambdaedge = lambda_.Function(
            self,
            f'{PROJECT}-{STAGE}-func-lambdaedge',
            function_name=f'{PROJECT}-{STAGE}-func-lambdaedge',
            code=lambda_.Code.from_inline(
                open('./function/src/lambdaedge.py').read().replace(
                    '__X_API_KEY__', public_api_key.attr_api_key)),
            handler='index.handler',
            runtime=lambda_.Runtime.PYTHON_3_7,
            timeout=core.Duration.seconds(30),
            memory_size=128,
            role=iam.Role(
                self,
                f'{PROJECT}-{STAGE}-func-lambdaedge-role',
                assumed_by=iam.CompositePrincipal(
                    iam.ServicePrincipal('edgelambda.amazonaws.com'),
                    iam.ServicePrincipal('lambda.amazonaws.com'),
                ),
                managed_policies=[
                    iam.ManagedPolicy.from_aws_managed_policy_name(
                        'service-role/AWSLambdaBasicExecutionRole'),
                ],
            ),
        )
        lambdaedge_version = func_lambdaedge.add_version(
            hashlib.sha256(
                open('./function/src/lambdaedge.py').read().replace(
                    '__X_API_KEY__',
                    public_api_key.attr_api_key).encode()).hexdigest())

        # ACM
        certificates = acm.Certificate(
            self,
            'certificates',
            domain_name=DOMAIN,
            validation_method=acm.ValidationMethod.DNS,
        )

        # CDN
        cdn = cloudfront.CloudFrontWebDistribution(
            self,
            f'{PROJECT}-{STAGE}-cloudfront',
            origin_configs=[
                cloudfront.SourceConfiguration(
                    behaviors=[
                        # default behavior
                        cloudfront.Behavior(
                            allowed_methods=cloudfront.
                            CloudFrontAllowedMethods.ALL,
                            default_ttl=core.Duration.seconds(0),
                            max_ttl=core.Duration.seconds(0),
                            min_ttl=core.Duration.seconds(0),
                            is_default_behavior=True,
                            lambda_function_associations=[
                                cloudfront.LambdaFunctionAssociation(
                                    event_type=cloudfront.LambdaEdgeEventType.
                                    ORIGIN_REQUEST,
                                    lambda_function=lambdaedge_version,
                                ),
                            ])
                    ],
                    custom_origin_source=cloudfront.CustomOriginConfig(
                        domain_name=core.Fn.select(
                            2, core.Fn.split('/',
                                             public_api.attr_graph_ql_url)), ),
                )
            ],
            alias_configuration=cloudfront.AliasConfiguration(
                acm_cert_ref=certificates.certificate_arn,
                names=[DOMAIN],
                security_policy=cloudfront.SecurityPolicyProtocol.
                TLS_V1_2_2018,
            ),
            price_class=cloudfront.PriceClass.PRICE_CLASS_ALL,
        )
        core.CfnOutput(
            self,
            'cloudfront-domain',
            value=cdn.domain_name,
        )
Esempio n. 20
0
    def __init__(self, scope: core.Construct, id: str, region, domain,
                 **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        # VPC , we need one for ECS cluster ( sadly )
        vpc = ec2.Vpc.from_lookup(self, 'vpc', is_default=True)

        cluster = ecs.Cluster(self, 'Cluster', vpc=vpc)

        # Route53 & SSL Certificate
        zone = dns.HostedZone(self, "dns", zone_name=domain)

        dns.ARecord(self,
                    'MinecraftRecord',
                    zone=zone,
                    record_name='minecraft',
                    target=dns.RecordTarget(values=['1.2.3.4']))

        cert = acm.Certificate(
            self,
            'cert',
            domain_name=f'*.{domain}',
            validation=acm.CertificateValidation.from_dns(zone))

        # ECS ( Cluster, EFS, Task Def)
        fs = efs.FileSystem(self,
                            'EFS',
                            vpc=vpc,
                            removal_policy=core.RemovalPolicy.DESTROY)

        task_definition = ecs.FargateTaskDefinition(self,
                                                    'TaskDef',
                                                    memory_limit_mib=4096,
                                                    cpu=1024)

        container = task_definition.add_container(
            'MinecraftDocker',
            image=ecs.ContainerImage.from_registry('darevee/minecraft-aws'),
            logging=ecs.AwsLogDriver(stream_prefix='Minecraf'),
            cpu=1024,
            memory_limit_mib=4096)
        container.add_mount_points(
            ecs.MountPoint(container_path='/minecraft',
                           source_volume='efs',
                           read_only=False))
        cfn_task = container.task_definition.node.default_child
        cfn_task.add_property_override("Volumes", [{
            "EFSVolumeConfiguration": {
                "FilesystemId": fs.file_system_id
            },
            "Name": "efs"
        }])

        container.add_port_mappings(ecs.PortMapping(container_port=25565))

        sg = ec2.SecurityGroup(self, 'sg', vpc=vpc)
        sg.add_ingress_rule(peer=ec2.Peer.any_ipv4(),
                            connection=ec2.Port.tcp(25565),
                            description='Minecraft Access')
        sg.add_ingress_rule(peer=ec2.Peer.any_ipv4(),
                            connection=ec2.Port.tcp(25575),
                            description='RCONN Access')

        fs.connections.allow_default_port_from(sg)

        subnets = ",".join(vpc.select_subnets().subnet_ids)

        # Cognito ( For ApiGW Authentication)
        userpool = cognito.UserPool(
            self,
            'UserPool',
            user_invitation=cognito.UserInvitationConfig(
                email_body=
                """No cześć {username}, zostałeś zaproszony do naszego Minecraft!
                Twoje tymczasowe hasło to {####}
                """,
                email_subject="Zaproszenie do minecrafta"))

        # APIGW (Gateway, Lambdas, S3 Static content)

        # Lambda Starter
        starter = _lambda.Function(self,
                                   'Starter',
                                   runtime=_lambda.Runtime.PYTHON_3_8,
                                   handler='index.lambda_handler',
                                   code=_lambda.Code.asset('lambda/starter'),
                                   timeout=core.Duration.seconds(300),
                                   environment={
                                       'cluster': cluster.cluster_name,
                                       'subnets': subnets,
                                       'security_groups': sg.security_group_id,
                                       'task_definition':
                                       task_definition.task_definition_arn,
                                       'region': region,
                                       'zone_id': zone.hosted_zone_id,
                                       'domain': domain
                                   })

        starter.add_to_role_policy(
            iam.PolicyStatement(effect=iam.Effect.ALLOW,
                                resources=["*"],
                                actions=[
                                    "ecs:ListTasks", "ecs:DescribeTasks",
                                    "ec2:DescribeNetworkInterfaces"
                                ]))
        starter.add_to_role_policy(
            iam.PolicyStatement(
                effect=iam.Effect.ALLOW,
                resources=[task_definition.task_definition_arn],
                actions=["ecs:RunTask", "ecs:DescribeTasks"]))
        starter.add_to_role_policy(
            iam.PolicyStatement(effect=iam.Effect.ALLOW,
                                resources=[
                                    task_definition.task_role.role_arn,
                                    task_definition.execution_role.role_arn
                                ],
                                actions=["iam:PassRole"]))

        starter.add_to_role_policy(
            iam.PolicyStatement(effect=iam.Effect.ALLOW,
                                resources=[zone.hosted_zone_arn],
                                actions=["route53:ChangeResourceRecordSets"]))

        # S3 static webpage
        bucket = s3.Bucket(self,
                           "S3WWW",
                           public_read_access=True,
                           removal_policy=core.RemovalPolicy.DESTROY,
                           website_index_document="index.html")
        s3d.BucketDeployment(self,
                             "S3Deploy",
                             destination_bucket=bucket,
                             sources=[s3d.Source.asset("static_page")])

        status = _lambda.Function(self,
                                  'Status',
                                  runtime=_lambda.Runtime.PYTHON_3_8,
                                  handler='index.lambda_handler',
                                  code=_lambda.Code.asset('lambda/status'),
                                  environment={
                                      'url': f"https://minecrafter.{domain}",
                                      'domain': domain
                                  })

        # ApiGW
        apigw = api.LambdaRestApi(self,
                                  'ApiGW',
                                  handler=status,
                                  proxy=False,
                                  domain_name={
                                      "domain_name": f'minecrafter.{domain}',
                                      "certificate": cert
                                  },
                                  default_cors_preflight_options={
                                      "allow_origins": api.Cors.ALL_ORIGINS,
                                      "allow_methods": api.Cors.ALL_METHODS
                                  })

        start = apigw.root.add_resource('start')
        start.add_method('ANY', integration=api.LambdaIntegration(starter))

        apigw.root.add_method('ANY')

        dns.ARecord(self,
                    'PointDNSToApiGW',
                    zone=zone,
                    target=dns.RecordTarget.from_alias(
                        targets.ApiGateway(apigw)),
                    record_name=f"minecrafter.{domain}")