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))
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))
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())
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
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, )
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)
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, )
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, )
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)
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)
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
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)
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, )
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')
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, )
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}")