def __init__(self, app: App, id: str) -> None: super().__init__(app, id) # CloudWatch Logs Group log_group = logs.LogGroup( self, "logs", retention=logs.RetentionDays.ONE_DAY, removal_policy = RemovalPolicy.DESTROY ) # Custom EventBridge Bus custom_bus = events.EventBus( self, "bus", event_bus_name="test-bus-cdk" ) # EventBridge Rule rule = events.Rule( self, "rule", event_bus=custom_bus ) rule.add_event_pattern( source=["my-cdk-application"], detail_type=["message"] ) rule.add_target(targets.CloudWatchLogGroup(log_group)) CfnOutput( self, "LogGroupName", description="Name of CloudWatch Log Group", value=log_group.log_group_name )
def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: super().__init__(scope, construct_id, **kwargs) #SNS Topic MySnsTopic = sns.Topic(self, "MySnsTopic") # Custom EventBridge Bus custom_bus = events.EventBus(self, "bus", event_bus_name="test-bus-cdk") # EventBridge Rule rule = events.Rule(self, "rule", event_bus=custom_bus) # Event Pattern to filter events rule.add_event_pattern(source=["my-application"], detail_type=["message"]) # SNS topic as target for Eventbridge Rue rule.add_target(targets.SnsTopic(MySnsTopic)) # CDK Outputs CfnOutput(self, "SNS topic name", description="SNS topic name", value=MySnsTopic.topic_name) CfnOutput(self, "SNS topic ARN", description="SNS topic ARN", value=MySnsTopic.topic_arn)
def __init__(self, scope: core.Construct, id: str, bank_account_service: lambda_.Function, stage: Optional[str] = 'prod', **kwargs) -> None: super().__init__(scope, id+'-'+stage, **kwargs) # create SNS topic topic = sns.Topic(self, "BankTopic", display_name="SMSOutbound", topic_name="SMSOutbound") topic.add_subscription(subs.EmailSubscription(email_address="*****@*****.**")) # create the EventBridge stuff bus_name = 'banking-demo-events-'+stage bus = events.EventBus(self, id, event_bus_name=bus_name) events.Rule(self, "HUMAN_REVIEWED_APPLICATION", event_bus=bus, event_pattern=events.EventPattern( detail_type=["HUMAN_REVIEWED_APPLICATION"]), rule_name="HUMAN_REVIEWED_APPLICATION", enabled=True, targets=[ targets.SnsTopic(topic) ]) events.Rule(self, "APPLICATION_SUBMITTED", event_bus=bus, event_pattern=events.EventPattern( detail_type=["APPLICATION_SUBMITTED"]), rule_name="APPLICATION_SUBMITTED", enabled=True) events.Rule(self, "APPLICATION_APPROVED", event_bus=bus, event_pattern=events.EventPattern( detail_type=["APPLICATION_APPROVED"]), rule_name="APPLICATION_APPROVED", enabled=True, targets=[ targets.LambdaFunction(lambda_.Function.from_function_arn( self, "func", bank_account_service.function_arn)) ]) self._event_bus_arn = bus.event_bus_arn
def __init__(self, scope: core.Construct, id: str, dynamo_table: aws_dynamodb.Table) -> None: super().__init__(scope, id) if not dynamo_table: print('missing dynamo db parameter') raise TypeError('missing dynamo db stream arn parameter') self._parents_dir: str = get_git_root(Path(__file__)) self._log_utils_dir: Path = Path(f'{self._parents_dir}/log_utils') self._cloudwatch_logs_policy = iam.ManagedPolicy.from_aws_managed_policy_name( "service-role/AWSLambdaBasicExecutionRole") #### eventbridge -> event bus -> rule ## lambda puts event to event bus , a rule is triggered -> lambda is called with the event ## other destinations are possible # create event bus event_bus = aws_events.EventBus(scope=self, id=f'{id}TenantMgmtBus', event_bus_name=f'{id}TenantMgmtBus') # create lambdas self.dispatcher_lambda = self._create_dispatcher_lambda(id, event_bus) # trigger a lambda on a DynamoDB change, create an event source stream_event_source = aws_lambda_event_sources.DynamoEventSource( table=dynamo_table, starting_position=aws_lambda.StartingPosition.LATEST) # bind the event source to a lambda stream_event_source.bind(self.dispatcher_lambda)
def __init__(self, app: App, id: str) -> None: super().__init__(app, id) # SQS Queue queue = sqs.Queue( self, "queue", ) # Custom EventBridge Bus custom_bus = events.EventBus( self, "bus", event_bus_name="test-bus-cdk" ) # EventBridge Rule rule = events.Rule( self, "rule", event_bus=custom_bus ) rule.add_event_pattern( source=["my-cdk-application"], detail_type=["message-for-queue"] ) rule.add_target(targets.SqsQueue(queue)) # Stack Outputs CfnOutput( self, "QueueURL", description="URL of SQS Queue", value=queue.queue_url )
def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) # Model all required resources ## IAM Roles lambda_role = _iam.Role( self, id='lab1-bdc-lambda-role', assumed_by=_iam.ServicePrincipal('lambda.amazonaws.com')) ## EventBridge eb = _eb.EventBus(self, id="lab1-bdc-eventbus", event_bus_name="lab1-bdc-eventbus") eb_pattern = _eb.EventPattern(detail_type=["message-received"], ) ## AWS Lambda Functions fnLambda_dispatch = _lambda.Function( self, "lab1-bdc-function-dispatch", code=_lambda.AssetCode("../lambda-functions/dispatch-function"), handler="app.handler", timeout=core.Duration.seconds(60), role=lambda_role, runtime=_lambda.Runtime.PYTHON_3_8) fnLambda_dispatch.add_environment("EVENT_BUS_NAME", eb.event_bus_name) fnLambda_consume = _lambda.Function( self, "lab1-bdc-function-consume", code=_lambda.AssetCode("../lambda-functions/consume-function"), handler="app.handler", role=lambda_role, timeout=core.Duration.seconds(60), runtime=_lambda.Runtime.PYTHON_3_8) cw_policy_statement = _iam.PolicyStatement(effect=_iam.Effect.ALLOW) cw_policy_statement.add_actions("logs:CreateLogGroup") cw_policy_statement.add_actions("logs:CreateLogStream") cw_policy_statement.add_actions("logs:PutLogEvents") cw_policy_statement.add_actions("logs:DescribeLogStreams") cw_policy_statement.add_resources("*") lambda_role.add_to_policy(cw_policy_statement) eb_policy_statement = _iam.PolicyStatement(effect=_iam.Effect.ALLOW) eb_policy_statement.add_actions("events:PutEvents") eb_policy_statement.add_resources(eb.event_bus_arn) lambda_role.add_to_policy(eb_policy_statement) _eb.Rule(self, id="lab1-bdc-eventRule", description="A basic rule sample", enabled=True, event_bus=eb, event_pattern=eb_pattern, rule_name="BDC-BasicDispatchConsume", targets=[_ebt.LambdaFunction(handler=fnLambda_consume)])
def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) # ############################################################################## # Event Bus # ############################################################################## eventbus = events.EventBus( self, "EventBus", event_bus_name=self.node.try_get_context('service_name')) self.eventbus_arn = eventbus.event_bus_arn
def __init__(self, scope: core.Construct, id: builtins.str, landing_zone: IVpcLandingZone) -> None: super().__init__(scope, id) core.Tags.of(self).add('Component', FsiCollectionsEventing.__name__) self.event_bus = e.EventBus(self, 'EventBus', event_bus_name='Fsi{}-Collections'.format( landing_zone.zone_name)) self.archive = e.Archive( self, 'ArchiveEverything', source_event_bus=self.event_bus, archive_name='Persist-Everything', description='Default FsiCollections backup rule', retention=core.Duration.days(90), event_pattern=e.EventPattern())
def __init__(self, scope: Construct, construct_id: str, props: dict, **kwargs) -> None: super().__init__(scope, construct_id, **kwargs) self.namespace = props['namespace'] # namespace in camelcase ################################################################################ # Event Bus event_bus_name = "DataPortalEventBus" # TODO: change id, use namespace as basis event_bus = events.EventBus(scope=self, id="umccr_bus", event_bus_name=event_bus_name) # Creates GDS SQS queue for Illumina file events # sqs_queue = sqs.Queue(scope=self, id="UmccrEventBusIcaEnsQueue") # sqs_queue.grant_send_messages(iam.AccountPrincipal('079623148045')) ################################################################################ # Lambda # Lambda layers for shared libs util_lambda_layer = self.create_lambda_layer(scope=self, name="eb_util") # TODO: needs more investigation as integration is not straight forward schema_lambda_layer = self.create_lambda_layer(scope=self, name="schemas") # lambda environment variables lambda_env = { "EVENT_BUS_NAME": event_bus_name } # Lambda to manage workflow events orchestrator_lambda = self.create_standard_lambda(scope=self, name="orchestrator", layers=[util_lambda_layer, schema_lambda_layer], env=lambda_env) event_bus.grant_put_events_to(orchestrator_lambda) # Lambda to prepare BCL Convert workflows bcl_convert_lambda = self.create_standard_lambda(scope=self, name="bcl_convert", layers=[util_lambda_layer, schema_lambda_layer], env=lambda_env) event_bus.grant_put_events_to(bcl_convert_lambda) # Lambda to prepare WGS QC workflows dragen_wgs_qc_lambda = self.create_standard_lambda(scope=self, name="dragen_wgs_qc", layers=[util_lambda_layer, schema_lambda_layer], env=lambda_env) event_bus.grant_put_events_to(dragen_wgs_qc_lambda) # Lambda to prepare WGS somatic analysis workflows dragen_wgs_somatic_lambda = self.create_standard_lambda(scope=self, name="dragen_wgs_somatic", layers=[util_lambda_layer, schema_lambda_layer], env=lambda_env) event_bus.grant_put_events_to(dragen_wgs_somatic_lambda) # Lambda to submit WES workflows to ICA wes_launcher_lambda = self.create_standard_lambda(scope=self, name="wes_launcher", layers=[util_lambda_layer, schema_lambda_layer]) event_bus.grant_put_events_to(wes_launcher_lambda) # Lambda to handle GDS events (translating outside events into application events + dedup/persisting) gds_manager_lambda = self.create_standard_lambda(scope=self, name="gds_manager", layers=[util_lambda_layer]) event_bus.grant_put_events_to(gds_manager_lambda) # Lamda to handle ENS events (translating outside events into application events + dedup/persisting) ens_manager_lambda = self.create_standard_lambda(scope=self, name="ens_event_manager", layers=[util_lambda_layer, schema_lambda_layer], env=lambda_env) event_bus.grant_put_events_to(ens_manager_lambda) ens_manager_lambda.grant_invoke(wes_launcher_lambda) ################################################################################ # Event Rules setup # route ENS events to the orchestrator self.create_event_rule(name="WorkflowRun", bus=event_bus, handler=orchestrator_lambda, event_type=EventType.WRSC, event_source=EventSource.ENS_HANDLER) self.create_event_rule(name="SequenceRun", bus=event_bus, handler=orchestrator_lambda, event_type=EventType.SRSC, event_source=EventSource.ENS_HANDLER) # route orchestrator events on to their next steps self.create_event_rule(name="BclConvert", bus=event_bus, handler=bcl_convert_lambda, event_type=EventType.SRSC, event_source=EventSource.ORCHESTRATOR) self.create_event_rule(name="DragenWgsQc", bus=event_bus, handler=dragen_wgs_qc_lambda, event_type=EventType.DRAGEN_WGS_QC, event_source=EventSource.ORCHESTRATOR) self.create_event_rule(name="DragenWgsSomatic", bus=event_bus, handler=dragen_wgs_somatic_lambda, event_type=EventType.DRAGEN_WGS_SOMATIC, event_source=EventSource.ORCHESTRATOR) # route WES launch events to the WES launcher self.create_event_rule(name="BclConvertLaunch", bus=event_bus, handler=wes_launcher_lambda, event_type=EventType.WES_LAUNCH, event_source=EventSource.BCL_CONVERT) self.create_event_rule(name="DragenWgsQcLaunchRequest", bus=event_bus, handler=wes_launcher_lambda, event_type=EventType.WES_LAUNCH, event_source=EventSource.DRAGEN_WGS_QC) self.create_event_rule(name="DragenWgsSomaticLaunch", bus=event_bus, handler=wes_launcher_lambda, event_type=EventType.WES_LAUNCH, event_source=EventSource.DRAGEN_WGS_SOMATIC)
def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) ### # Let's create our own Event Bus for this rather than using default ### bus = events.EventBus(self, 'DestinedEventBus', event_bus_name='the-destined-lambda') ### # Destinations need invoked Asynchronously so let's use SNS ### topic = sns.Topic(self, 'theDestinedLambdaTopic', display_name='The Destined Lambda CDK Pattern Topic') ### # Lambda configured with success and failure destinations # Note the actual lambda has no EventBridge code inside it ### destined_lambda = _lambda.Function( self, "destinedLambda", runtime=_lambda.Runtime.NODEJS_12_X, handler="destinedLambda.handler", code=_lambda.Code.from_asset("lambda_fns"), retry_attempts=0, on_success=destinations.EventBridgeDestination(event_bus=bus), on_failure=destinations.EventBridgeDestination(event_bus=bus)) topic.add_subscription( subscriptions.LambdaSubscription(destined_lambda)) ### # This is a lambda that will be called by onSuccess for destinedLambda # It simply prints the event it receives to the cloudwatch logs ### success_lambda = _lambda.Function( self, "successLambda", runtime=_lambda.Runtime.NODEJS_12_X, handler="success.handler", code=_lambda.Code.from_asset("lambda_fns"), timeout=core.Duration.seconds(3)) ### # EventBridge Rule to send events to our success lambda # Notice how we can still do event filtering based on the json payload returned by the destined lambda ### success_rule = events.Rule( self, 'successRule', event_bus=bus, description= 'all success events are caught here and logged centrally', event_pattern=events.EventPattern( detail={ "requestContext": { "condition": ["Success"] }, "responsePayload": { "source": ["cdkpatterns.the-destined-lambda"], "action": ["message"] } })) success_rule.add_target(targets.LambdaFunction(success_lambda)) ### # This is a lambda that will be called by onFailure for destinedLambda # It simply prints the event it receives to the cloudwatch logs. # Notice how it includes the message that came into destined lambda to make it fail so you have # everything you need to do retries or manually investigate ### failure_lambda = _lambda.Function( self, "failureLambda", runtime=_lambda.Runtime.NODEJS_12_X, handler="failure.handler", code=_lambda.Code.from_asset("lambda_fns"), timeout=core.Duration.seconds(3)) ### # EventBridge Rule to send events to our failure lambda ### failure_rule = events.Rule( self, 'failureRule', event_bus=bus, description= 'all failure events are caught here and logged centrally', event_pattern=events.EventPattern( detail={"responsePayload": { "errorType": ["Error"] }})) failure_rule.add_target(targets.LambdaFunction(failure_lambda)) ### # API Gateway Creation # This is complicated because it transforms the incoming json payload into a query string url # this url is used to post the payload to sns without a lambda inbetween ### gateway = api_gw.RestApi( self, 'theDestinedLambdaAPI', deploy_options=api_gw.StageOptions( metrics_enabled=True, logging_level=api_gw.MethodLoggingLevel.INFO, data_trace_enabled=True, stage_name='prod')) # Give our gateway permissions to interact with SNS api_gw_sns_role = iam.Role( self, 'ApiGatewaySNSRole', assumed_by=iam.ServicePrincipal('apigateway.amazonaws.com')) topic.grant_publish(api_gw_sns_role) # shortening the lines of later code schema = api_gw.JsonSchema schema_type = api_gw.JsonSchemaType # Because this isn't a proxy integration, we need to define our response model response_model = gateway.add_model( 'ResponseModel', content_type='application/json', model_name='ResponseModel', schema=schema( schema=api_gw.JsonSchemaVersion.DRAFT4, title='pollResponse', type=schema_type.OBJECT, properties={'message': schema(type=schema_type.STRING)})) error_response_model = gateway.add_model( 'ErrorResponseModel', content_type='application/json', model_name='ErrorResponseModel', schema=schema(schema=api_gw.JsonSchemaVersion.DRAFT4, title='errorResponse', type=schema_type.OBJECT, properties={ 'state': schema(type=schema_type.STRING), 'message': schema(type=schema_type.STRING) })) request_template = "Action=Publish&" + \ "TargetArn=$util.urlEncode('" + topic.topic_arn + "')&" + \ "Message=please $input.params().querystring.get('mode')&" + \ "Version=2010-03-31" # This is the VTL to transform the error response error_template = { "state": 'error', "message": "$util.escapeJavaScript($input.path('$.errorMessage'))" } error_template_string = json.dumps(error_template, separators=(',', ':')) # This is how our gateway chooses what response to send based on selection_pattern integration_options = api_gw.IntegrationOptions( credentials_role=api_gw_sns_role, request_parameters={ 'integration.request.header.Content-Type': "'application/x-www-form-urlencoded'" }, request_templates={"application/json": request_template}, passthrough_behavior=api_gw.PassthroughBehavior.NEVER, integration_responses=[ api_gw.IntegrationResponse( status_code='200', response_templates={ "application/json": json.dumps({"message": 'Message added to SNS topic'}) }), api_gw.IntegrationResponse( selection_pattern="^\[Error\].*", status_code='400', response_templates={ "application/json": error_template_string }, response_parameters={ 'method.response.header.Content-Type': "'application/json'", 'method.response.header.Access-Control-Allow-Origin': "'*'", 'method.response.header.Access-Control-Allow-Credentials': "'true'" }) ]) # Add an SendEvent endpoint onto the gateway gateway.root.add_resource('SendEvent') \ .add_method('GET', api_gw.Integration(type=api_gw.IntegrationType.AWS, integration_http_method='POST', uri='arn:aws:apigateway:us-east-1:sns:path//', options=integration_options ), method_responses=[ api_gw.MethodResponse(status_code='200', response_parameters={ 'method.response.header.Content-Type': True, 'method.response.header.Access-Control-Allow-Origin': True, 'method.response.header.Access-Control-Allow-Credentials': True }, response_models={ 'application/json': response_model }), api_gw.MethodResponse(status_code='400', response_parameters={ 'method.response.header.Content-Type': True, 'method.response.header.Access-Control-Allow-Origin': True, 'method.response.header.Access-Control-Allow-Credentials': True }, response_models={ 'application/json': error_response_model }), ] )
def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) with open("stack/config.yml", 'r') as stream: configs = yaml.safe_load(stream) ### S3 core images_S3_bucket = _s3.Bucket(self, "ICS_IMAGES") images_S3_bucket.add_cors_rule( allowed_methods=[_s3.HttpMethods.POST], allowed_origins=["*"] # add API gateway web resource URL ) ### SQS core image_deadletter_queue = _sqs.Queue(self, "ICS_IMAGES_DEADLETTER_QUEUE") image_queue = _sqs.Queue(self, "ICS_IMAGES_QUEUE", dead_letter_queue={ "max_receive_count": configs["DeadLetterQueue"]["MaxReceiveCount"], "queue": image_deadletter_queue }) ### api gateway core api_gateway = RestApi(self, 'ICS_API_GATEWAY', rest_api_name='ImageContentSearchApiGateway') api_gateway_resource = api_gateway.root.add_resource(configs["ProjectName"]) api_gateway_landing_page_resource = api_gateway_resource.add_resource('web') api_gateway_get_signedurl_resource = api_gateway_resource.add_resource('signedUrl') api_gateway_image_search_resource = api_gateway_resource.add_resource('search') ### landing page function get_landing_page_function = Function(self, "ICS_GET_LANDING_PAGE", function_name="ICS_GET_LANDING_PAGE", runtime=Runtime.PYTHON_3_7, handler="main.handler", code=Code.asset("./src/landingPage")) get_landing_page_integration = LambdaIntegration( get_landing_page_function, proxy=True, integration_responses=[{ 'statusCode': '200', 'responseParameters': { 'method.response.header.Access-Control-Allow-Origin': "'*'", } }]) api_gateway_landing_page_resource.add_method('GET', get_landing_page_integration, method_responses=[{ 'statusCode': '200', 'responseParameters': { 'method.response.header.Access-Control-Allow-Origin': True, } }]) ### cognito required_attribute = _cognito.StandardAttribute(required=True) users_pool = _cognito.UserPool(self, "ICS_USERS_POOL", auto_verify=_cognito.AutoVerifiedAttrs(email=True), #required for self sign-up standard_attributes=_cognito.StandardAttributes(email=required_attribute), #required for self sign-up self_sign_up_enabled=configs["Cognito"]["SelfSignUp"]) user_pool_app_client = _cognito.CfnUserPoolClient(self, "ICS_USERS_POOL_APP_CLIENT", supported_identity_providers=["COGNITO"], allowed_o_auth_flows=["implicit"], allowed_o_auth_scopes=configs["Cognito"]["AllowedOAuthScopes"], user_pool_id=users_pool.user_pool_id, callback_ur_ls=[api_gateway_landing_page_resource.url], allowed_o_auth_flows_user_pool_client=True, explicit_auth_flows=["ALLOW_REFRESH_TOKEN_AUTH"]) user_pool_domain = _cognito.UserPoolDomain(self, "ICS_USERS_POOL_DOMAIN", user_pool=users_pool, cognito_domain=_cognito.CognitoDomainOptions(domain_prefix=configs["Cognito"]["DomainPrefix"])) ### get signed URL function get_signedurl_function = Function(self, "ICS_GET_SIGNED_URL", function_name="ICS_GET_SIGNED_URL", environment={ "ICS_IMAGES_BUCKET": images_S3_bucket.bucket_name, "DEFAULT_SIGNEDURL_EXPIRY_SECONDS": configs["Functions"]["DefaultSignedUrlExpirySeconds"] }, runtime=Runtime.PYTHON_3_7, handler="main.handler", code=Code.asset("./src/getSignedUrl")) get_signedurl_integration = LambdaIntegration( get_signedurl_function, proxy=True, integration_responses=[{ 'statusCode': '200', 'responseParameters': { 'method.response.header.Access-Control-Allow-Origin': "'*'", } }]) api_gateway_get_signedurl_authorizer = CfnAuthorizer(self, "ICS_API_GATEWAY_GET_SIGNED_URL_AUTHORIZER", rest_api_id=api_gateway_get_signedurl_resource.rest_api.rest_api_id, name="ICS_API_GATEWAY_GET_SIGNED_URL_AUTHORIZER", type="COGNITO_USER_POOLS", identity_source="method.request.header.Authorization", provider_arns=[users_pool.user_pool_arn]) api_gateway_get_signedurl_resource.add_method('GET', get_signedurl_integration, authorization_type=AuthorizationType.COGNITO, method_responses=[{ 'statusCode': '200', 'responseParameters': { 'method.response.header.Access-Control-Allow-Origin': True, } }] ).node.find_child('Resource').add_property_override('AuthorizerId', api_gateway_get_signedurl_authorizer.ref) images_S3_bucket.grant_put(get_signedurl_function, objects_key_pattern="new/*") ### image massage function image_massage_function = Function(self, "ICS_IMAGE_MASSAGE", function_name="ICS_IMAGE_MASSAGE", timeout=core.Duration.seconds(6), runtime=Runtime.PYTHON_3_7, environment={"ICS_IMAGE_MASSAGE": image_queue.queue_name}, handler="main.handler", code=Code.asset("./src/imageMassage")) images_S3_bucket.grant_write(image_massage_function, "processed/*") images_S3_bucket.grant_delete(image_massage_function, "new/*") images_S3_bucket.grant_read(image_massage_function, "new/*") new_image_added_notification = _s3notification.LambdaDestination(image_massage_function) images_S3_bucket.add_event_notification(_s3.EventType.OBJECT_CREATED, new_image_added_notification, _s3.NotificationKeyFilter(prefix="new/") ) image_queue.grant_send_messages(image_massage_function) ### image analyzer function image_analyzer_function = Function(self, "ICS_IMAGE_ANALYSIS", function_name="ICS_IMAGE_ANALYSIS", runtime=Runtime.PYTHON_3_7, timeout=core.Duration.seconds(10), environment={ "ICS_IMAGES_BUCKET": images_S3_bucket.bucket_name, "DEFAULT_MAX_CALL_ATTEMPTS": configs["Functions"]["DefaultMaxApiCallAttempts"], "REGION": core.Aws.REGION, }, handler="main.handler", code=Code.asset("./src/imageAnalysis")) image_analyzer_function.add_event_source(_lambda_event_source.SqsEventSource(queue=image_queue, batch_size=10)) image_queue.grant_consume_messages(image_massage_function) lambda_rekognition_access = _iam.PolicyStatement( effect=_iam.Effect.ALLOW, actions=["rekognition:DetectLabels", "rekognition:DetectModerationLabels"], resources=["*"] ) image_analyzer_function.add_to_role_policy(lambda_rekognition_access) images_S3_bucket.grant_read(image_analyzer_function, "processed/*") ### API gateway finalizing self.add_cors_options(api_gateway_get_signedurl_resource) self.add_cors_options(api_gateway_landing_page_resource) self.add_cors_options(api_gateway_image_search_resource) ### database database_secret = _secrets_manager.Secret(self, "ICS_DATABASE_SECRET", secret_name="rds-db-credentials/image-content-search-rds-secret", generate_secret_string=_secrets_manager.SecretStringGenerator( generate_string_key='password', secret_string_template='{"username": "******"}', exclude_punctuation=True, exclude_characters='/@\" \\\'', require_each_included_type=True ) ) database = _rds.CfnDBCluster(self, "ICS_DATABASE", engine=_rds.DatabaseClusterEngine.aurora_mysql(version=_rds.AuroraMysqlEngineVersion.VER_5_7_12).engine_type, engine_mode="serverless", database_name=configs["Database"]["Name"], enable_http_endpoint=True, deletion_protection=configs["Database"]["DeletionProtection"], master_username=database_secret.secret_value_from_json("username").to_string(), master_user_password=database_secret.secret_value_from_json("password").to_string(), scaling_configuration=_rds.CfnDBCluster.ScalingConfigurationProperty( auto_pause=configs["Database"]["Scaling"]["AutoPause"], min_capacity=configs["Database"]["Scaling"]["Min"], max_capacity=configs["Database"]["Scaling"]["Max"], seconds_until_auto_pause=configs["Database"]["Scaling"]["SecondsToAutoPause"] ), ) database_cluster_arn = "arn:aws:rds:{}:{}:cluster:{}".format(core.Aws.REGION, core.Aws.ACCOUNT_ID, database.ref) secret_target = _secrets_manager.CfnSecretTargetAttachment(self,"ICS_DATABASE_SECRET_TARGET", target_type="AWS::RDS::DBCluster", target_id=database.ref, secret_id=database_secret.secret_arn ) secret_target.node.add_dependency(database) ### database function image_data_function_role = _iam.Role(self, "ICS_IMAGE_DATA_FUNCTION_ROLE", role_name="ICS_IMAGE_DATA_FUNCTION_ROLE", assumed_by=_iam.ServicePrincipal("lambda.amazonaws.com"), managed_policies=[ _iam.ManagedPolicy.from_aws_managed_policy_name("service-role/AWSLambdaVPCAccessExecutionRole"), _iam.ManagedPolicy.from_aws_managed_policy_name("service-role/AWSLambdaBasicExecutionRole"), _iam.ManagedPolicy.from_aws_managed_policy_name("AmazonRDSDataFullAccess") ] ) image_data_function = Function(self, "ICS_IMAGE_DATA", function_name="ICS_IMAGE_DATA", runtime=Runtime.PYTHON_3_7, timeout=core.Duration.seconds(5), role=image_data_function_role, environment={ "DEFAULT_MAX_CALL_ATTEMPTS": configs["Functions"]["DefaultMaxApiCallAttempts"], "CLUSTER_ARN": database_cluster_arn, "CREDENTIALS_ARN": database_secret.secret_arn, "DB_NAME": database.database_name, "REGION": core.Aws.REGION }, handler="main.handler", code=Code.asset("./src/imageData") ) image_search_integration = LambdaIntegration( image_data_function, proxy=True, integration_responses=[{ 'statusCode': '200', 'responseParameters': { 'method.response.header.Access-Control-Allow-Origin': "'*'", } }]) api_gateway_image_search_authorizer = CfnAuthorizer(self, "ICS_API_GATEWAY_IMAGE_SEARCH_AUTHORIZER", rest_api_id=api_gateway_image_search_resource.rest_api.rest_api_id, name="ICS_API_GATEWAY_IMAGE_SEARCH_AUTHORIZER", type="COGNITO_USER_POOLS", identity_source="method.request.header.Authorization", provider_arns=[users_pool.user_pool_arn]) api_gateway_image_search_resource.add_method('POST', image_search_integration, authorization_type=AuthorizationType.COGNITO, method_responses=[{ 'statusCode': '200', 'responseParameters': { 'method.response.header.Access-Control-Allow-Origin': True, } }] ).node.find_child('Resource').add_property_override('AuthorizerId', api_gateway_image_search_authorizer.ref) lambda_access_search = _iam.PolicyStatement( effect=_iam.Effect.ALLOW, actions=["translate:TranslateText"], resources=["*"] ) image_data_function.add_to_role_policy(lambda_access_search) ### custom resource lambda_provider = Provider(self, 'ICS_IMAGE_DATA_PROVIDER', on_event_handler=image_data_function ) core.CustomResource(self, 'ICS_IMAGE_DATA_RESOURCE', service_token=lambda_provider.service_token, pascal_case_properties=False, resource_type="Custom::SchemaCreation", properties={ "source": "Cloudformation" } ) ### event bridge event_bus = _events.EventBus(self, "ICS_IMAGE_CONTENT_BUS") event_rule = _events.Rule(self, "ICS_IMAGE_CONTENT_RULE", rule_name="ICS_IMAGE_CONTENT_RULE", description="The event from image analyzer to store the data", event_bus=event_bus, event_pattern=_events.EventPattern(resources=[image_analyzer_function.function_arn]), ) event_rule.add_target(_event_targets.LambdaFunction(image_data_function)) event_bus.grant_put_events(image_analyzer_function) image_analyzer_function.add_environment("EVENT_BUS", event_bus.event_bus_name) ### outputs core.CfnOutput(self, 'CognitoHostedUILogin', value='https://{}.auth.{}.amazoncognito.com/login?client_id={}&response_type=token&scope={}&redirect_uri={}'.format(user_pool_domain.domain_name, core.Aws.REGION, user_pool_app_client.ref, '+'.join(user_pool_app_client.allowed_o_auth_scopes), api_gateway_landing_page_resource.url), description='The Cognito Hosted UI Login Page' )
def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: super().__init__(scope, construct_id, **kwargs) # vpc_name = self.node.try_get_context("vpc_name") # vpc = aws_ec2.Vpc.from_lookup(self, "ExistingVPC", # is_default=True, # vpc_name=vpc_name) vpc = aws_ec2.Vpc( self, "FirehoseToS3VPC", max_azs=2, gateway_endpoints={ "S3": aws_ec2.GatewayVpcEndpointOptions( service=aws_ec2.GatewayVpcEndpointAwsService.S3) }) ASYNC_CALLEE_LAMBDA_FN_NAME = "LambdaAsyncCallee" async_callee_lambda_fn = aws_lambda.Function( self, "LambdaAsyncCallee", runtime=aws_lambda.Runtime.PYTHON_3_7, function_name="LambdaAsyncCallee", handler="lambda_aync_callee.lambda_handler", description= "Lambda function asynchrously invoked by LambdaAsyncCaller", code=aws_lambda.Code.from_asset( os.path.join(os.path.dirname(__file__), 'src/main/python')), timeout=cdk.Duration.minutes(5)) log_group = aws_logs.LogGroup( self, "LambdaAsyncCalleeLogGroup", #XXX: Circular dependency between resources occurs # if aws_lambda.Function.function_name is used # instead of literal name of lambda function such as "LambdaAsyncCallee" log_group_name="/aws/lambda/{}".format( ASYNC_CALLEE_LAMBDA_FN_NAME), retention=aws_logs.RetentionDays.THREE_DAYS, removal_policy=cdk.RemovalPolicy.DESTROY) log_group.grant_write(async_callee_lambda_fn) event_bus = aws_events.EventBus( self, "EventBusForLambda", event_bus_name="EventBusForLambdaDestinations", ) event_bus.apply_removal_policy(cdk.RemovalPolicy.DESTROY) log_group = aws_logs.LogGroup( self, "EventBusLogGroup", log_group_name="/aws/events/{}".format(event_bus.event_bus_name), retention=aws_logs.RetentionDays.THREE_DAYS, removal_policy=cdk.RemovalPolicy.DESTROY) event_rule = aws_events.Rule( self, "EventRuleForLambdaDestinations", rule_name="EventRuleForLambdaDestinations", event_bus=event_bus, event_pattern={"account": [self.account]}) event_rule.add_target(aws_events_targets.CloudWatchLogGroup(log_group)) event_rule.apply_removal_policy(cdk.RemovalPolicy.DESTROY) CALLER_LAMBDA_FN_NAME = "LambdaAsyncCaller" caller_lambda_fn = aws_lambda.Function( self, "LambdaAsyncCaller", runtime=aws_lambda.Runtime.PYTHON_3_7, function_name="LambdaAsyncCaller", handler="lambda_caller.lambda_handler", description="Asynchronusly call lambda function", code=aws_lambda.Code.from_asset( os.path.join(os.path.dirname(__file__), 'src/main/python')), timeout=cdk.Duration.minutes(5), #XXX: Uncomments out if you want to use different lambda function version # current_version_options=aws_lambda.VersionOptions( # on_success=aws_lambda_destinations.LambdaDestination(async_callee_lambda_fn, response_only=False), # on_failure=aws_lambda_destinations.EventBridgeDestination(event_bus), # max_event_age=cdk.Duration.hours(6), # Minimum: 60 seconds, Maximum: 6 hours, Default: 6 hours # retry_attempts=0 # Minimum: 0, Maximum: 2, Default: 2 # ), on_success=aws_lambda_destinations.LambdaDestination( async_callee_lambda_fn, response_only=False), on_failure=aws_lambda_destinations.EventBridgeDestination( event_bus), max_event_age=cdk.Duration.hours( 6), # Minimum: 60 seconds Maximum: 6 hours, Default: 6 hours #XXX: Set retry_attempts to 0 in order to invoke other lambda function as soon as a error occurred retry_attempts=0 # Minimum: 0, Maximum: 2, Default: 2 ) sns_topic = aws_sns.Topic(self, 'SnsTopicForLambda', topic_name='LambdaSourceEvent', display_name='lambda source event') caller_lambda_fn.add_event_source( aws_lambda_event_sources.SnsEventSource(sns_topic)) caller_lambda_fn.add_to_role_policy( aws_iam.PolicyStatement( effect=aws_iam.Effect.ALLOW, #XXX: The ARN will be formatted as follows: # arn:{partition}:{service}:{region}:{account}:{resource}{sep}}{resource-name} resources=[ self.format_arn( partition="aws", service="lambda", region=cdk.Aws.REGION, account=cdk.Aws.ACCOUNT_ID, resource="function", resource_name="{}*".format( async_callee_lambda_fn.function_name), arn_format=cdk.ArnFormat.COLON_RESOURCE_NAME) ], actions=["lambda:InvokeFunction"])) caller_lambda_fn.add_to_role_policy( aws_iam.PolicyStatement( effect=aws_iam.Effect.ALLOW, #XXX: The ARN will be formatted as follows: # arn:{partition}:{service}:{region}:{account}:{resource}{sep}}{resource-name} resources=[event_bus.event_bus_arn], actions=["events:PutEvents"])) log_group = aws_logs.LogGroup( self, "LambdaAsyncCallerLogGroup", #XXX: Circular dependency between resources occurs # if aws_lambda.Function.function_name is used # instead of literal name of lambda function such as "LambdaAsyncCaller" log_group_name="/aws/lambda/{}".format(CALLER_LAMBDA_FN_NAME), retention=aws_logs.RetentionDays.THREE_DAYS, removal_policy=cdk.RemovalPolicy.DESTROY) log_group.grant_write(caller_lambda_fn) cdk.CfnOutput(self, 'SNSTopicName', value=sns_topic.topic_name, export_name='SNSTopicName') cdk.CfnOutput(self, 'SNSTopicArn', value=sns_topic.topic_arn, export_name='SNSTopicArn')
def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) dynamodb_table = _ddb.Table( self, id="lab2-cm-ddb", table_name="lab2-cm-order-status", partition_key=Attribute(name='ID', type=AttributeType.STRING), removal_policy=core.RemovalPolicy.DESTROY # NOT for production ) eb = _eb.EventBus(self, id="lab2-cm-eventbus", event_bus_name="lab2-cm-eventbus") lambda_role = _iam.Role( self, id='lab2-cm-role', assumed_by=_iam.ServicePrincipal('lambda.amazonaws.com')) dynamodb_policy_statement = _iam.PolicyStatement( effect=_iam.Effect.ALLOW) dynamodb_policy_statement.add_actions("dynamodb:*") dynamodb_policy_statement.add_resources(dynamodb_table.table_arn) lambda_role.add_to_policy(dynamodb_policy_statement) eventbridge_policy_statement = _iam.PolicyStatement( effect=_iam.Effect.ALLOW) eventbridge_policy_statement.add_actions("events:*") eventbridge_policy_statement.add_resources(eb.event_bus_arn) lambda_role.add_to_policy(eventbridge_policy_statement) cloudwatch_policy_statement = _iam.PolicyStatement( effect=_iam.Effect.ALLOW) cloudwatch_policy_statement.add_actions("logs:CreateLogGroup") cloudwatch_policy_statement.add_actions("logs:CreateLogStream") cloudwatch_policy_statement.add_actions("logs:PutLogEvents") cloudwatch_policy_statement.add_actions("logs:DescribeLogStreams") cloudwatch_policy_statement.add_resources("*") lambda_role.add_to_policy(cloudwatch_policy_statement) fn_lambda_invoice_service = aws_lambda.Function( self, "lab2-cm-invoiceService", code=aws_lambda.AssetCode("../lambda-functions/invoice-service/"), handler="app.lambda_handler", tracing=aws_lambda.Tracing.ACTIVE, timeout=core.Duration.seconds(30), role=lambda_role, runtime=aws_lambda.Runtime.PYTHON_3_8) fn_lambda_invoice_service.add_environment("TABLE_NAME", dynamodb_table.table_name) fn_lambda_fulfilment_service = aws_lambda.Function( self, "lab2-cm-fulfilmentService", code=aws_lambda.AssetCode( "../lambda-functions/fulfilment-service/"), handler="app.lambda_handler", tracing=aws_lambda.Tracing.ACTIVE, timeout=core.Duration.seconds(30), role=lambda_role, runtime=aws_lambda.Runtime.PYTHON_3_8) fn_lambda_fulfilment_service.add_environment("TABLE_NAME", dynamodb_table.table_name) fn_lambda_fulfilment_service.add_environment("EVENTBUS_NAME", eb.event_bus_name) fn_lambda_forecasting_service = aws_lambda.Function( self, "lab2-cm-forecastingService", code=aws_lambda.AssetCode( "../lambda-functions/forecasting-service/"), handler="app.lambda_handler", tracing=aws_lambda.Tracing.ACTIVE, timeout=core.Duration.seconds(30), role=lambda_role, runtime=aws_lambda.Runtime.PYTHON_3_8) fn_lambda_forecasting_service.add_environment( "TABLE_NAME", dynamodb_table.table_name) fn_lambda_order_service = aws_lambda.Function( self, "lab2-cm-orderService", code=aws_lambda.AssetCode("../lambda-functions/order-service/"), handler="app.lambda_handler", timeout=core.Duration.seconds(30), tracing=aws_lambda.Tracing.ACTIVE, role=lambda_role, runtime=aws_lambda.Runtime.PYTHON_3_8) fn_lambda_order_service.add_environment("TABLE_NAME", dynamodb_table.table_name) fn_lambda_order_service.add_environment("EVENTBUS_NAME", eb.event_bus_name) fn_lambda_logistic_service = aws_lambda.Function( self, "lab2-cm-logisticService", code=aws_lambda.AssetCode("../lambda-functions/logistic-service/"), handler="app.lambda_handler", timeout=core.Duration.seconds(30), tracing=aws_lambda.Tracing.ACTIVE, role=lambda_role, runtime=aws_lambda.Runtime.PYTHON_3_8) fn_lambda_logistic_service.add_environment("TABLE_NAME", dynamodb_table.table_name) eb_order_created_pattern = _eb.EventPattern( detail_type=["order_created"], ) eb_fulfilment_completed_pattern = _eb.EventPattern( detail_type=["fulfilment_completed"], ) eb_order_created_rule = _eb.Rule( self, id="lab2-cm-eventRule-order-created", description="Order created event", enabled=True, event_bus=eb, event_pattern=eb_order_created_pattern, rule_name="lab2-OrderCreated", targets=[ _ebt.LambdaFunction(handler=fn_lambda_invoice_service), _ebt.LambdaFunction(handler=fn_lambda_fulfilment_service), _ebt.LambdaFunction(handler=fn_lambda_forecasting_service) ]) eb_fulfilment_completed_rule = _eb.Rule( self, id="lab2-cm-eventRule-fulfilment-completed", description="Fulfilment completedevent", enabled=True, event_bus=eb, event_pattern=eb_fulfilment_completed_pattern, rule_name="lab2-FulfilmentCompleted", targets=[_ebt.LambdaFunction(handler=fn_lambda_logistic_service)]) api = _ag.RestApi( self, id='lab2-cm-api-gateway', ) api_lambda_integration = _ag.LambdaIntegration(fn_lambda_order_service) api.root.add_resource('order').add_method('GET', api_lambda_integration)
def __init__(self, scope: core.Construct, construct_id: str, **kwargs): super().__init__(scope, construct_id, **kwargs) self._eventBus = _events.EventBus(self, "MyLanguageBus")
def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) table = ddb.Table(self, 'StripeSampleCustomers', partition_key={ 'name': 'CustomerID', 'type': ddb.AttributeType.STRING }) bus = events.EventBus(self, 'stripeAppEventBus', event_bus_name='stripeAppEventBus') lambda_role_for_go = iam.Role( self, "Role", role_name='stripeAppRole', assumed_by=iam.ServicePrincipal("lambda.amazonaws.com"), managed_policies=[ iam.ManagedPolicy.from_aws_managed_policy_name( "service-role/AWSLambdaBasicExecutionRole"), iam.ManagedPolicy.from_aws_managed_policy_name( "AmazonEventBridgeFullAccess"), iam.ManagedPolicy.from_aws_managed_policy_name( "SecretsManagerReadWrite") ]) customer_created_handler = _lambda.Function( self, "createStripeCustomerHandler", runtime=_lambda.Runtime.GO_1_X, code=_lambda.Code.asset('lambda/stripe-create-customer'), handler='createCustomerHandler', timeout=core.Duration.seconds(8), role=lambda_role_for_go, environment={ 'CUSTOMER_TABLE_NAME': table.table_name, }) table.grant_read_write_data(customer_created_handler) go_lambda = _lambda.Function( self, "stripeWebhookEventHandler", runtime=_lambda.Runtime.GO_1_X, code=_lambda.Code.asset('lambda/stripe-webhook-handler'), handler='stripeWebhookHandler', timeout=core.Duration.seconds(8), role=lambda_role_for_go, ) _apigw.LambdaRestApi(self, "stripeWebhookAPI", handler=go_lambda) customer_created_handler.add_permission( "createStripeCustomerHandlerPermission", principal=iam.ServicePrincipal("events.amazonaws.com"), action='lambda:InvokeFunction', source_arn=go_lambda.function_arn) go_lambda.add_permission( "stripeWebhookHandlerPermission", principal=iam.ServicePrincipal("lambda.amazonaws.com"), action='lambda:InvokeFunction', source_arn=customer_created_handler.function_arn) event = events.Rule( self, 'stripeWebhookEventRule', rule_name='stripeWebhookEventRule', enabled=True, event_bus=bus, description= 'all success events are caught here and logged centrally', event_pattern=events.EventPattern( detail={"stripeEvent": ["customer.subscription.created"]}, source=["stripeWebHookHandler.lambda"])) event.add_target(targets.LambdaFunction(customer_created_handler))
def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) # Model all required resources ''' Define IAM role that will be used for AWS Lambda Functions ''' lambda_role = _iam.Role( self, id='lab1-bdc-lambda-role', assumed_by=_iam.ServicePrincipal('lambda.amazonaws.com')) ''' Define Amazon EventBridge Construct and also pattern to be included later. ''' eb = _eb.EventBus(self, id="lab1-bdc-eventbus", event_bus_name="lab1-bdc-eventbus") eb_pattern = _eb.EventPattern(detail_type=["message-received"], ) ''' These lines below define construct for our AWS Lambda Functions. There are 2 Lambda functions that we need to create: dispatch and consume. As the dispatch function need to add environment variable, noticed that we add an env_var into AWS Lambda Function that later could be retrieved within the function. ''' fnLambda_dispatch = _lambda.Function( self, "lab1-bdc-function-dispatch", code=_lambda.AssetCode("../lambda-functions/dispatch-function"), handler="app.handler", timeout=core.Duration.seconds(60), role=lambda_role, runtime=_lambda.Runtime.PYTHON_3_8) fnLambda_dispatch.add_environment("EVENT_BUS_NAME", eb.event_bus_name) fnLambda_consume = _lambda.Function( self, "lab1-bdc-function-consume", code=_lambda.AssetCode("../lambda-functions/consume-function"), handler="app.handler", role=lambda_role, timeout=core.Duration.seconds(60), runtime=_lambda.Runtime.PYTHON_3_8) cw_policy_statement = _iam.PolicyStatement(effect=_iam.Effect.ALLOW) cw_policy_statement.add_actions("logs:CreateLogGroup") cw_policy_statement.add_actions("logs:CreateLogStream") cw_policy_statement.add_actions("logs:PutLogEvents") cw_policy_statement.add_actions("logs:DescribeLogStreams") cw_policy_statement.add_resources("*") lambda_role.add_to_policy(cw_policy_statement) eb_policy_statement = _iam.PolicyStatement(effect=_iam.Effect.ALLOW) eb_policy_statement.add_actions("events:PutEvents") eb_policy_statement.add_resources(eb.event_bus_arn) lambda_role.add_to_policy(eb_policy_statement) _eb.Rule(self, id="lab1-bdc-eventRule", description="A basic rule sample", enabled=True, event_bus=eb, event_pattern=eb_pattern, rule_name="BDC-BasicDispatchConsume", targets=[_ebt.LambdaFunction(handler=fnLambda_consume)])