def __init__(self, scope: core.Construct, id: str, common_stack: CommonStack, **kwargs) -> None: super().__init__(scope, id, **kwargs) self._supported_in_region = self.are_services_supported_in_region( ["lambda"]) aws_lambda.Function( self, "EchoHandler", runtime=aws_lambda.Runtime.PYTHON_3_7, code=aws_lambda.Code.asset("lambda"), handler="echo_handler.handler", function_name="echo", ) echo_first = aws_lambda.Function( self, "EchoFirstHandler", runtime=aws_lambda.Runtime.PYTHON_3_7, code=aws_lambda.Code.asset("lambda"), handler="echo_handler_first.handler", function_name="echoFirst", ) echo_first.add_version("1") aws_lambda.Alias(self, "alias", alias_name="alias", version=echo_first.latest_version) common_stack.add_to_common_role_policies(self)
def __init__( self, scope: core.Construct, id: str, name, lambda_code_bucket, environment, timeout=30, memory_size=128, vpc_id=None, security_group_id=None, handler=None, ): super().__init__(scope, id) self.stack_name = core.Stack.of(self).stack_name environment = { key: str(val) for key, val in environment.items() if val } if not handler: handler = f"{name}.handler" function_props = { "function_name": f"{self.stack_name}-{name}", "runtime": aws_lambda.Runtime.PYTHON_3_8, "code": aws_lambda.Code.from_bucket( bucket=lambda_code_bucket, key=f"{self.stack_name}/{name}.zip" ), "handler": handler, "timeout": core.Duration.seconds(timeout), "memory_size": memory_size, "environment": environment, "log_retention": logs.RetentionDays.SIX_MONTHS, } if vpc_id and security_group_id: opencast_vpc = ec2.Vpc.from_lookup( self, "OpencastVpc", vpc_id=vpc_id ) opencast_security_group = ec2.SecurityGroup.from_security_group_id( self, "OpencastSecurityGroup", security_group_id=security_group_id, ) function_props.update( { "vpc": opencast_vpc, "security_groups": [opencast_security_group], } ) self.function = aws_lambda.Function(self, "function", **function_props) self.alias = aws_lambda.Alias( self, "alias", version=self.function.add_version("$LATEST"), description="initial release", alias_name=names.LAMBDA_RELEASE_ALIAS, )
def create_deployment_group(self, group_name, handler): version = handler.add_version(datetime.now().isoformat()) alias = lambda_.Alias(self, f'{group_name}LambdaAlias', alias_name="Dev", version=version) codedeploy.LambdaDeploymentGroup( self, f'Deploy{group_name}Lambda', alias=alias, deployment_config=codedeploy.LambdaDeploymentConfig.ALL_AT_ONCE, )
def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) # The code that defines your stack goes here my_lambda = _lambda.Function( self, 'HelloHandler', runtime=_lambda.Runtime.PYTHON_3_7, code=_lambda.Code.asset('lambda'), handler='hello.handler', ) version01 = _lambda.Version(self, "version01", lambda_=my_lambda) alias_beta = _lambda.Alias(self, "alias_beta", alias_name="beta", version=version01) #当我创建v3的时候我可以使用下面的代码,为v2创建一个新的别名alias_v2 #v2=_lambda.Version.from_version_arn(self,"v",version_arn="arn:aws-cn:lambda:cn-northwest-1:188642756190:function:lab08-HelloHandler2E4FBA4D-1D2KNU1L6W08T:2") #alias_v2= _lambda.Alias(self,"alias_v2",alias_name="alias_v2",version=version01) #始终保持别名prod在最新的版本 alias_prod = _lambda.Alias(self, "prod", alias_name="prod", version=my_lambda.current_version) # v5=_lambda.Version.from_version_arn(self,"v5",version_arn="arn:aws-cn:lambda:cn-northwest-1:188642756190:function:lab08-HelloHandler2E4FBA4D-1UZFGVUVZPTQJ:5") # alias_prod= _lambda.Alias(self,"prod",alias_name="prod",version=v5) lab03_alb = elb.ApplicationLoadBalancer(self, "lab03_alb", vpc=lab03_vpc, internet_facing=True) alb_listener = lab03_alb.add_listener("lab03_alb_listener", port=80) alb_listener.add_targets('Target', targets=[_targets.LambdaTarget(fn=my_lambda)])
def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) role_arn = 'arn:aws:iam::315207712355:role/lbrole' role = iam.Role.from_role_arn(self, id='role_id', role_arn=role_arn) # The code that defines your stack goes here this_dir = path.dirname(__file__) handler = lmb.Function(self, 'Handler', runtime=lmb.Runtime.PYTHON_3_7, role=role, handler='handler.handler', code=lmb.Code.from_asset( path.join(this_dir, 'lambda'))) alias = lmb.Alias(self, 'HandlerAlias', alias_name='Current', version=handler.current_version) gw = apigw.LambdaRestApi( self, 'Gateway', description='Endpoint for a simple Lambda-powered web service', handler=alias) failure_alarm = cloudwatch.Alarm(self, 'FailureAlarm', metric=cloudwatch.Metric( metric_name='5XXError', namespace='AWS/ApiGateway', dimensions={ 'ApiName': 'Gateway', }, statistic='Sum', period=core.Duration.minutes(1)), threshold=1, evaluation_periods=1) codedeploy.LambdaDeploymentGroup( self, 'DeploymentGroup', alias=alias, deployment_config=codedeploy.LambdaDeploymentConfig. CANARY_10_PERCENT_10_MINUTES, alarms=[failure_alarm]) self.url_output = core.CfnOutput(self, 'Url', value=gw.url)
def attach_alias_to_version(self, version_obj: aws_lambda.Version) -> (str, str): """ Creates a version alias for the given version of the lambda :return: The version alias string """ version_alias_associated_version = version_obj.version version_alias_name = "integ_test_current_version_alias" aws_lambda.Alias( self, "integ_test_lambda_current_version_alias", version=version_obj, alias_name=version_alias_name, ) return version_alias_associated_version, version_alias_name
def __init__(self, app: core.App, id: str, **kwargs): super().__init__(app, id, **kwargs) # [ Lambda: Code ] # # This represents the code to be supplied by the pipeline. self.lambda_code = lambda_.Code.from_cfn_parameters() # [ Lambda: Function ] # # Creates the Lambda. func = lambda_.Function( self, "Lambda", code=self.lambda_code, handler="index.handler", runtime=lambda_.Runtime.PYTHON_3_7, ) # [ Lambda: Version ] # # Adds versions to the Lambda with date of code execution. version = func.add_version(datetime.now().isoformat()) # [ Lambda: Alias ] # # Adds aliasing to the Lambda to allow for blue-green deployment. alias = lambda_.Alias(self, "LambdaAlias", alias_name="Prod", version=version) # [ CodeDeploy: Deployment Group ] # # Creates the group for Lambda(s) for the Aliases. codedeploy.LambdaDeploymentGroup( self, "DeploymentGroup", alias=alias, deployment_config=codedeploy.LambdaDeploymentConfig. LINEAR_10_PERCENT_EVERY_1_MINUTE)
def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) this_dir = path.dirname(__file__) handler = lmb.Function(self, 'Handler', runtime=lmb.Runtime.PYTHON_3_7, handler='handler.handler', code=lmb.Code.from_asset(path.join(this_dir, 'lambda')) ) # For canary deployments alias = lmb.Alias(self, 'HandlerAlias', alias_name='Current', version=handler.current_version ) gw = apigw.LambdaRestApi(self, 'Gateway', description='Endpoint for app', handler=alias ) failure_alarm = cloudwatch.Alarm(self, 'FailureAlarm', metric=cloudwatch.Metric( metric_name='5XXError', namespace='AWS/ApiGateway', dimensions={ 'ApiName': 'Gateway' }, statistic='Sum', period=core.Duration.minutes(1) ), threshold=1, evaluation_periods=1 ) codedeploy.LambdaDeploymentGroup(self, 'Deploy', alias=alias, deployment_config=codedeploy.LambdaDeploymentConfig.CANARY_10_PERCENT_10_MINUTES, alarms=[failure_alarm] ) self.url_output = core.CfnOutput(self, 'Url', value=gw.url )
def __init__(self, app: core.App, id: str, config, **kwargs): super().__init__(app, id, **kwargs) self.lambda_code = lambda_.Code.from_cfn_parameters() func = lambda_.Function(self, "Lambda", function_name=config["Default"]["project"] + "-lambda-" + randomness, code=self.lambda_code, handler="index.handler", runtime=lambda_.Runtime.NODEJS_12_X, tracing=lambda_.Tracing.ACTIVE) api = apigateway.RestApi(self, "lambda-service", rest_api_name=config["Default"]["project"] + "-api-" + randomness, description="This service serves the lambda.", deploy_options={ "logging_level": apigateway.MethodLoggingLevel.INFO, "tracing_enabled": True }) get_lambda_integration = apigateway.LambdaIntegration( func, request_templates={"text/html": '{ "statusCode": "200" }'}) api.root.add_method("GET", get_lambda_integration) # GET / version = func.latest_version alias = lambda_.Alias(self, "LambdaAlias", alias_name="Prod", version=version) codedeploy.LambdaDeploymentGroup( self, "DeploymentGroup", alias=alias, deployment_config=codedeploy.LambdaDeploymentConfig. LINEAR_10_PERCENT_EVERY_1_MINUTE)
def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) function_arn = ssm.StringParameter.value_for_string_parameter( self, "/iot-gg-cicd-workshop/function/function_arn") version = awslambda.Version.from_version_arn(self, "Version", version_arn=function_arn) prod_lambda_alias = awslambda.Alias( self, "LambdaAlias", alias_name="PROD", version=version, ) ssm.StringParameter( self, "ProdVersionArnParameter", parameter_name="/iot-gg-cicd-workshop/function/prod_version_arn", string_value=prod_lambda_alias.function_arn, )
def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) self.lambda_code = awslambda.Code.asset("src/lambda") greengrass_lambda = awslambda.Function( self, "Lambda", runtime=awslambda.Runtime.PYTHON_3_7, code=self.lambda_code, handler="device_shadow.handler", function_name="iot-gg-cicd-workshop-function", ) version = greengrass_lambda.current_version cfn_version: awslambda.CfnVersion = version.node.try_find_child( "Resource") cfn_version.cfn_options.deletion_policy = core.CfnDeletionPolicy.RETAIN canary_lambda_alias = awslambda.Alias( self, "LambdaAlias", alias_name="CANARY", version=version, ) ssm.StringParameter( self, "FunctionArnParameter", parameter_name="/iot-gg-cicd-workshop/function/function_arn", string_value="{}:{}".format(greengrass_lambda.function_arn, version.version), ) ssm.StringParameter( self, "CanaryVersionArnParameter", parameter_name="/iot-gg-cicd-workshop/function/canary_version_arn", string_value=canary_lambda_alias.function_arn, )
def __init__(self, stack: core.Construct, lambda_app: codedeploy.LambdaApplication, name: str): """Creates the underlying Lambda, Lambda Alias, and Deployment Group necessary to run this Lambda in the SpamDetectionPipeline stack. This code assumes the Lambda's handler can be invoked by the snake case verison of the name with `.handler` appended. :param stack: The stack. :param lambda_app: The Lambda Application that will control the deployments. :param name: The camel case name for this Lambda. """ self.__name = name # Create the underlying Lambda function on the stack. self.__lambda = _lambda.Function( stack, name, runtime=_lambda.Runtime.PYTHON_3_7, code=_lambda.Code.asset('lambda'), handler=_convert_camel_case_to_snake_case(name) + '.handler', ) # Create the production alias to use when we want to refer to this Lambda. version = self.__lambda.add_version(_get_pipeline_lambda_version()) self.__lambda_alias = _lambda.Alias(stack, name + 'Prod', version=version, alias_name='prod') # Create the deployment group that will be used to updated the Lambda # based on the alias. codedeploy.LambdaDeploymentGroup( stack, name + 'DN', alias=self.__lambda_alias, application=lambda_app, deployment_config=codedeploy.LambdaDeploymentConfig.ALL_AT_ONCE, )
def __init__(self, scope: core.Construct, id: str, stack_log_level: str, back_end_api_name: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) # Read Lambda Code): try: with open( "secure_api_with_throttling/stacks/back_end/lambda_src/serverless_greeter.py", mode="r") as f: greeter_fn_code = f.read() except OSError as e: print("Unable to read Lambda Function Code") raise e greeter_fn = _lambda.Function( self, "greeterFn", function_name=f"greeter_fn_{id}", runtime=_lambda.Runtime.PYTHON_3_7, handler="index.lambda_handler", code=_lambda.InlineCode(greeter_fn_code), timeout=core.Duration.seconds(10), # reserved_concurrent_executions=2, environment={ "LOG_LEVEL": f"{stack_log_level}", "Environment": "Production", "RANDOM_SLEEP_SECS": "10", "ANDON_CORD_PULLED": "False" }, description="Creates a simple greeter function") greeter_fn_version = greeter_fn.latest_version greeter_fn_version_alias = _lambda.Alias( self, "greeterFnAlias", alias_name="MystiqueAutomation", version=greeter_fn_version) # Create Custom Loggroup greeter_fn_lg = _logs.LogGroup( self, "squareFnLoggroup", log_group_name=f"/aws/lambda/{greeter_fn.function_name}", retention=_logs.RetentionDays.ONE_WEEK, removal_policy=core.RemovalPolicy.DESTROY) # Add API GW front end for the Lambda back_end_api_stage_01_options = _apigw.StageOptions( stage_name="miztiik-unthrottled", logging_level=_apigw.MethodLoggingLevel.INFO) # Create API Gateway unthrottled_api = _apigw.RestApi( self, "backEnd01Api", rest_api_name=f"{back_end_api_name}", deploy_options=back_end_api_stage_01_options, endpoint_types=[_apigw.EndpointType.EDGE], description= f"{GlobalArgs.OWNER}: API Security Automation demonstration using - Unthrottled API" ) back_end_01_api_res = unthrottled_api.root.add_resource("unsecure") greeter = back_end_01_api_res.add_resource("greeter") greeter_method_get = greeter.add_method( http_method="GET", request_parameters={ "method.request.header.InvocationType": True, "method.request.path.number": True }, integration=_apigw.LambdaIntegration(handler=greeter_fn, proxy=True)) # Outputs output_1 = core.CfnOutput( self, "UnthrottledApiUrl", value=f"{greeter.url}", description= "Use an utility like artitllery to generate load against this API." )
def __init__(self, scope: core.Construct, id: str, stack_log_level: str, back_end_api_name: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) # Create Serverless Event Processor using Lambda): # Read Lambda Code): self.s1 = "" self.delimiter = self.s1 self.s = self.delimiter try: with open( "secure_private_api/stacks/back_end/lambda_src/serverless_greeter.py", mode="r") as f: unsecure_greeter_fn_code = f.read() except OSError as e: print("Unable to read Lambda Function Code") raise e unsecure_greeter_fn = _lambda.Function( self, "unSecureGreeterFn", function_name="unsecure_greeter_fn", runtime=_lambda.Runtime.PYTHON_3_7, handler="index.lambda_handler", code=_lambda.InlineCode(unsecure_greeter_fn_code), timeout=core.Duration.seconds(15), reserved_concurrent_executions=1, environment={ "LOG_LEVEL": f"{stack_log_level}", "Environment": "Production", "ANDON_CORD_PULLED": "False" }) unsecure_greeter_fn_version = unsecure_greeter_fn.latest_version unsecure_greeter_fn_version_alias = _lambda.Alias( self, "greeterFnAlias", alias_name="MystiqueAutomation", version=unsecure_greeter_fn_version) # Create Custom Loggroup # /aws/lambda/function-name unsecure_greeter_fn_lg = _logs.LogGroup( self, "squareFnLoggroup", log_group_name=f"/aws/lambda/{unsecure_greeter_fn.function_name}", retention=_logs.RetentionDays.ONE_WEEK, removal_policy=core.RemovalPolicy.DESTROY) # Add API GW front end for the Lambda back_end_01_api_stage_options = _apigw.StageOptions( stage_name="miztiik", throttling_rate_limit=10, throttling_burst_limit=100, logging_level=_apigw.MethodLoggingLevel.INFO) # Create API Gateway unsecure_public_api_01 = _apigw.RestApi( self, "backEnd01Api", rest_api_name=f"{back_end_api_name}", deploy_options=back_end_01_api_stage_options, endpoint_types=[_apigw.EndpointType.REGIONAL]) back_end_01_api_res = unsecure_public_api_01.root.add_resource( "unsecure") greeter = back_end_01_api_res.add_resource("greeter") greeter_method_get = greeter.add_method( http_method="GET", request_parameters={ "method.request.header.InvocationType": True, "method.request.path.number": True }, integration=_apigw.LambdaIntegration(handler=unsecure_greeter_fn, proxy=True)) # Outputs output_1 = core.CfnOutput( self, "ApiUrl", value=f"{greeter.url}", description="Use a browser to access this url.")
def __init__(self, scope: core.Construct, id: str, vpc, efs_sg, efs_share, efs_ap, stack_log_level: str, back_end_api_name: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) # Create Serverless Event Processor using Lambda): # Read Lambda Code): try: with open( "lambda_with_efs/stacks/back_end/lambda_src/serverless_greeter.py", mode="r") as f: greeter_fn_code = f.read() except OSError as e: print("Unable to read Lambda Function Code") raise e greeter_fn = _lambda.Function( self, "secureGreeterFn", function_name=f"greeter_fn_{id}", runtime=_lambda.Runtime.PYTHON_3_7, handler="index.lambda_handler", code=_lambda.InlineCode(greeter_fn_code), current_version_options={ "removal_policy": core.RemovalPolicy.DESTROY, # retain old versions "retry_attempts": 1, "description": "Mystique Factory Build Version" }, timeout=core.Duration.seconds(15), reserved_concurrent_executions=20, retry_attempts=1, environment={ "LOG_LEVEL": f"{stack_log_level}", "Environment": "Production", "ANDON_CORD_PULLED": "False", "RANDOM_SLEEP_ENABLED": "False" }, description= "A simple greeter function, which responds with a timestamp", vpc=vpc, vpc_subnets=_ec2.SubnetType.PRIVATE, security_groups=[efs_sg], filesystem=_lambda.FileSystem.from_efs_access_point( efs_ap, '/mnt/efs')) greeter_fn_version = greeter_fn.latest_version greeter_fn_dev_alias = _lambda.Alias( self, "greeterFnMystiqueAutomationAlias", alias_name="MystiqueAutomation", version=greeter_fn_version) # greeter_fn_version_alias = greeter_fn.current_version.add_alias("dev") # greeter_fn_prod_alias = greeter_fn.current_version.add_alias("prod") # Create Custom Loggroup # /aws/lambda/function-name greeter_fn_lg = _logs.LogGroup( self, "greeterFnLoggroup", log_group_name=f"/aws/lambda/{greeter_fn.function_name}", retention=_logs.RetentionDays.ONE_WEEK, removal_policy=core.RemovalPolicy.DESTROY) # Permissions to mount EFS (CDK May add them automatically) # roleStmt1 = _iam.PolicyStatement( # effect=_iam.Effect.ALLOW, # resources=[ # f"arn:aws:elasticfilesystem:{core.Aws.REGION}:{core.Aws.ACCOUNT_ID}:file-system/{efs_share.file_system_id}" # ], # actions=["elasticfilesystem:*"] # ) # roleStmt1.sid = "AllowLambdaToReadWriteToEfs" # greeter_fn.add_to_role_policy(roleStmt1) # %% wa_api_logs = _logs.LogGroup( self, "waApiLogs", log_group_name=f"/aws/apigateway/{back_end_api_name}/access_logs", removal_policy=core.RemovalPolicy.DESTROY, retention=_logs.RetentionDays.ONE_DAY) ####################################### ## CONFIG FOR API STAGE : PROD ## ####################################### # Add API GW front end for the Lambda prod_api_stage_options = _apigw.StageOptions( stage_name="prod", throttling_rate_limit=10, throttling_burst_limit=100, # Log full requests/responses data data_trace_enabled=True, # Enable Detailed CloudWatch Metrics metrics_enabled=True, logging_level=_apigw.MethodLoggingLevel.INFO, access_log_destination=_apigw.LogGroupLogDestination(wa_api_logs), variables={ "lambdaAlias": "prod", "appOwner": "Mystique" }) # Create API Gateway wa_api = _apigw.RestApi( self, "backEnd01Api", rest_api_name=f"{back_end_api_name}", deploy_options=prod_api_stage_options, endpoint_types=[_apigw.EndpointType.EDGE], description= f"{GlobalArgs.OWNER}: API Best Practices. This stack deploys an API and integrates with Lambda $LATEST alias." ) wa_api_res = wa_api.root.add_resource("well-architected-api") greetings_wall = wa_api_res.add_resource("message-wall") # Add GET method to API greetings_wall_get = greetings_wall.add_method( http_method="GET", request_parameters={ "method.request.header.InvocationType": True, "method.request.path.mystique": True }, integration=_apigw.LambdaIntegration(handler=greeter_fn, proxy=True)) # Add POST method to API greeter_method_get = greetings_wall.add_method( http_method="POST", request_parameters={ "method.request.header.InvocationType": True, "method.request.path.mystique": True }, integration=_apigw.LambdaIntegration(handler=greeter_fn, proxy=True)) # Add DELETE method to API greeter_method_get = greetings_wall.add_method( http_method="DELETE", request_parameters={ "method.request.header.InvocationType": True, "method.request.path.mystique": True }, integration=_apigw.LambdaIntegration(handler=greeter_fn, proxy=True)) # Outputs output_0 = core.CfnOutput( self, "AutomationFrom", value=f"{GlobalArgs.SOURCE_INFO}", description= "To know more about this automation stack, check out our github page." ) output_1 = core.CfnOutput( self, "GreetingsWallApiUrl", value=f"{greetings_wall.url}", description= "Use an utility like curl from the same VPC as the API to invoke it." )
def __init__( self, scope: cdk.Construct, construct_id: str, stack_log_level: str, vpc, kafka_client_sg, kafka_topic_name: str, **kwargs ) -> None: super().__init__(scope, construct_id, **kwargs) # Add your stack resources below): ######################################## ####### ####### ####### Stream Data Producer ####### ####### ####### ######################################## # Create AWS Kafka Layer kafka_layer = _lambda.LayerVersion( self, "kafkaLayer", code=_lambda.Code.from_asset( "stacks/back_end/serverless_kafka_producer_stack/lambda_src/layer_code/kafka_python3.zip"), compatible_runtimes=[ _lambda.Runtime.PYTHON_3_7, _lambda.Runtime.PYTHON_3_8 ], license=f"Mystique Lambda Layer of kafka, Refer to AWS for license.", description="Layer to for latest version of kafka" ) # Read Lambda Code try: with open( "stacks/back_end/serverless_kafka_producer_stack/lambda_src/stream_data_producer.py", encoding="utf-8", mode="r", ) as f: data_producer_fn_code = f.read() except OSError: print("Unable to read Lambda Function Code") raise data_producer_fn = _lambda.Function( self, "streamDataProducerFn", function_name=f"data_producer_{construct_id}", description="Produce streaming data events and push to Kafka Topic", runtime=_lambda.Runtime.PYTHON_3_7, code=_lambda.InlineCode(data_producer_fn_code), handler="index.lambda_handler", timeout=cdk.Duration.seconds(10), reserved_concurrent_executions=1, environment={ "LOG_LEVEL": "INFO", "APP_ENV": "Production", "TRIGGER_RANDOM_DELAY": "True", "STORE_EVENTS_TOPIC": f"{kafka_topic_name}", "KAFKA_BOOTSTRAP_SRV": "", "LD_LIBRARY_PATH": "/opt/python" }, layers=[kafka_layer], security_group=kafka_client_sg, vpc=vpc, vpc_subnets=_ec2.SubnetType.PRIVATE ) # Grant our Lambda Producer privileges to write to S3 # sales_event_bkt.grant_read_write(data_producer_fn) data_producer_fn_version = data_producer_fn.latest_version data_producer_fn_version_alias = _lambda.Alias( self, "streamDataProducerFnAlias", alias_name="MystiqueAutomation", version=data_producer_fn_version, ) # Create Custom Loggroup for Producer data_producer_lg = _logs.LogGroup( self, "streamDataProducerFnLogGroup", log_group_name=f"/aws/lambda/{data_producer_fn.function_name}", removal_policy=cdk.RemovalPolicy.DESTROY, retention=_logs.RetentionDays.ONE_DAY, ) # Restrict Produce Lambda to be invoked only from the stack owner account data_producer_fn.add_permission( "restrictLambdaInvocationToOwnAccount", principal=_iam.AccountRootPrincipal(), action="lambda:InvokeFunction", source_account=cdk.Aws.ACCOUNT_ID, # source_arn=sales_event_bkt.bucket_arn ) # https://docs.aws.amazon.com/lambda/latest/dg/lambda-intro-execution-role.html roleStmt1 = _iam.PolicyStatement( effect=_iam.Effect.ALLOW, resources=['*'], actions=['ec2:CreateNetworkInterface', 'ec2:DescribeNetworkInterfaces', 'ec2:DeleteNetworkInterface'] ) roleStmt1.sid = "AllowLambdaToManageVPCENI" data_producer_fn.add_to_role_policy(roleStmt1) ########################################### ################# OUTPUTS ################# ########################################### output_0 = cdk.CfnOutput( self, "AutomationFrom", value=f"{GlobalArgs.SOURCE_INFO}", description="To know more about this automation stack, check out our github page.", ) output_1 = cdk.CfnOutput( self, "SaleOrderEventsProducer", value=f"https://console.aws.amazon.com/lambda/home?region={cdk.Aws.REGION}#/functions/{data_producer_fn.function_name}", description="Produce streaming data events and push to S3 Topic.", )
def __init__( self, scope: core.Construct, id: str, stack_log_level: str, back_end_api_name: str, back_end_api_datastore_name: str, **kwargs ) -> None: super().__init__(scope, id, **kwargs) # DynamoDB: Key-Value Database): if not back_end_api_datastore_name: back_end_api_datastore_name = f"{GlobalArgs.REPO_NAME}-api-datastore" self.ddb_table_01 = _dynamodb.Table( self, "apiPerformanceWithCaching", partition_key=_dynamodb.Attribute( name="id", type=_dynamodb.AttributeType.STRING ), read_capacity=20, write_capacity=20, table_name=f"{back_end_api_datastore_name}-{id}", removal_policy=core.RemovalPolicy.DESTROY ) # Let us use our Cfn Custom Resource to load data into our dynamodb table. data_loader_status = DdbDataLoaderStack( self, "cachedApiDdbLoader", Ddb_table_name=self.ddb_table_01.table_name ) # Read Lambda Code): try: with open("api_performance_with_caching/stacks/back_end/lambda_src/serverless_greeter.py", mode="r") as f: greeter_fn_code = f.read() except OSError as e: print("Unable to read Lambda Function Code") raise e greeter_fn = _lambda.Function( self, "greeterFn", function_name=f"greeter_fn_{id}", runtime=_lambda.Runtime.PYTHON_3_7, handler="index.lambda_handler", code=_lambda.InlineCode(greeter_fn_code), timeout=core.Duration.seconds(10), reserved_concurrent_executions=50, environment={ "LOG_LEVEL": f"{stack_log_level}", "Environment": "Production", "DDB_TABLE_NAME": self.ddb_table_01.table_name, "RANDOM_SLEEP_SECS": "2", "ANDON_CORD_PULLED": "False" }, description="Creates a simple greeter function" ) greeter_fn_version = greeter_fn.latest_version greeter_fn_version_alias = _lambda.Alias( self, "greeterFnAlias", alias_name="MystiqueAutomation", version=greeter_fn_version ) # Create Custom Loggroup greeter_fn_lg = _logs.LogGroup( self, "squareFnLoggroup", log_group_name=f"/aws/lambda/{greeter_fn.function_name}", retention=_logs.RetentionDays.ONE_WEEK, removal_policy=core.RemovalPolicy.DESTROY ) # Add DDB Read Write Permission to the Lambda self.ddb_table_01.grant_read_write_data(greeter_fn) # Add API GW front end for the Lambda back_end_api_stage_01_options = _apigw.StageOptions( stage_name="miztiik", cache_cluster_enabled=True, caching_enabled=True, cache_cluster_size="0.5", cache_ttl=core.Duration.seconds(30), # Log full requests/responses data data_trace_enabled=True, # Enable Detailed CloudWatch Metrics metrics_enabled=True, logging_level=_apigw.MethodLoggingLevel.INFO, method_options={ "/cached/movie/GET": _apigw.MethodDeploymentOptions( caching_enabled=False ) } ) # Create API Gateway cached_api = _apigw.RestApi( self, "backEnd01Api", rest_api_name=f"{back_end_api_name}", deploy_options=back_end_api_stage_01_options, minimum_compression_size=0, endpoint_types=[ _apigw.EndpointType.EDGE ], description=f"{GlobalArgs.OWNER}: API Best Practice Demonstration - Cached-vs-UnCached APIs" ) back_end_01_api_res = cached_api.root.add_resource("cached") res_movie = back_end_01_api_res.add_resource( "movie" ) res_movie_method_get = res_movie.add_method( http_method="GET", request_parameters={ "method.request.header.InvocationType": True, "method.request.path.number": True }, integration=_apigw.LambdaIntegration( handler=greeter_fn, proxy=True ) ) # Add Method for getting Movie by {id} res_movie_by_id = res_movie.add_resource("{id}") # Because this is NOT a proxy integration, we need to define our response model response_model = cached_api.add_model( "ResponseModel", content_type="application/json", model_name="MiztiikResponseModel", schema=_apigw.JsonSchema( schema=_apigw.JsonSchemaVersion.DRAFT4, title="updateResponse", type=_apigw.JsonSchemaType.OBJECT, properties={ "message": _apigw.JsonSchema(type=_apigw.JsonSchemaType.STRING) } ) ) res_movie_by_id_validator_request = cached_api.add_request_validator( "apiReqValidator", validate_request_parameters=True ) req_template = { "id": "$input.params('id')" } request_template_string = json.dumps( req_template, separators=(',', ':')) # resp_template = """$input.path('$.body.message')""" resp_template = """$input.path('$.body')""" res_movie_by_id_method_get = res_movie_by_id.add_method( http_method="GET", request_parameters={ "method.request.header.InvocationType": False, "method.request.path.id": True }, request_validator=res_movie_by_id_validator_request, integration=_apigw.LambdaIntegration( handler=greeter_fn, proxy=False, request_parameters={ "integration.request.path.id": "method.request.path.id" }, cache_key_parameters=[ "method.request.path.id" ], request_templates={ "application/json": request_template_string }, passthrough_behavior=_apigw.PassthroughBehavior.NEVER, integration_responses=[ _apigw.IntegrationResponse( status_code="200", # selection_pattern="2\d{2}", # Use for mapping Lambda Errors response_parameters={ "method.response.header.Access-Control-Allow-Headers": "'cache-control,Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'", "method.response.header.Content-Type": "'application/json'", }, response_templates={ "application/json": f"{resp_template}" } ) ] ), method_responses=[ _apigw.MethodResponse( status_code="200", response_parameters={ "method.response.header.Content-Type": True, "method.response.header.Access-Control-Allow-Headers": True, }, response_models={ "application/json": response_model } ) ] ) self.cached_api_url = res_movie.url # Outputs output_1 = core.CfnOutput( self, "CachedApiUrl", value=f"{res_movie.url}", description="Use an utility like curl/Postman to access this API." ) output_2 = core.CfnOutput( self, "ddbDataLoaderStatus", value=f"{data_loader_status.response}", description="Waf Rate Rule Creator Status" )
def __init__(self, scope: core.Construct, id: str, vpc, efs_sg, efs_share, efs_ap_nginx, stack_log_level: str, back_end_api_name: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) # Create Serverless Event Processor using Lambda): # Read Lambda Code): try: with open( "fargate_with_efs/stacks/back_end/lambda_src/serverless_greeter.py", mode="r") as f: greeter_fn_code = f.read() except OSError as e: print("Unable to read Lambda Function Code") raise e efs_mnt_path = "/mnt/html" greeter_fn = _lambda.Function( self, "secureGreeterFn", function_name=f"greeter_fn_{id}", runtime=_lambda.Runtime.PYTHON_3_7, handler="index.lambda_handler", code=_lambda.InlineCode(greeter_fn_code), current_version_options={ "removal_policy": core.RemovalPolicy.DESTROY, # retain old versions "retry_attempts": 1, "description": "Mystique Factory Build Version" }, timeout=core.Duration.seconds(15), reserved_concurrent_executions=20, retry_attempts=1, environment={ "LOG_LEVEL": f"{stack_log_level}", "Environment": "Production", "ANDON_CORD_PULLED": "False", "RANDOM_SLEEP_ENABLED": "False", "EFS_MNT_PATH": efs_mnt_path }, description= "A simple greeter function, which responds with a timestamp", vpc=vpc, vpc_subnets=_ec2.SubnetType.PRIVATE, security_groups=[efs_sg], filesystem=_lambda.FileSystem.from_efs_access_point( efs_ap_nginx, efs_mnt_path)) greeter_fn_version = greeter_fn.latest_version greeter_fn_dev_alias = _lambda.Alias( self, "greeterFnMystiqueAutomationAlias", alias_name="MystiqueAutomation", version=greeter_fn_version, description= "Mystique Factory Build Version to ingest content from API GW to EFS", retry_attempts=1) # Create Custom Loggroup greeter_fn_lg = _logs.LogGroup( self, "greeterFnLoggroup", log_group_name=f"/aws/lambda/{greeter_fn.function_name}", retention=_logs.RetentionDays.ONE_WEEK, removal_policy=core.RemovalPolicy.DESTROY) # %% wa_api_logs = _logs.LogGroup( self, "waApiLogs", log_group_name=f"/aws/apigateway/{back_end_api_name}/access_logs", removal_policy=core.RemovalPolicy.DESTROY, retention=_logs.RetentionDays.ONE_DAY) ####################################### ## CONFIG FOR API STAGE : PROD ## ####################################### # Add API GW front end for the Lambda prod_api_stage_options = _apigw.StageOptions( stage_name="prod", throttling_rate_limit=10, throttling_burst_limit=100, # Log full requests/responses data data_trace_enabled=True, # Enable Detailed CloudWatch Metrics metrics_enabled=True, logging_level=_apigw.MethodLoggingLevel.INFO, access_log_destination=_apigw.LogGroupLogDestination(wa_api_logs), variables={ "lambdaAlias": "prod", "appOwner": "Mystique" }) # Create API Gateway wa_api = _apigw.RestApi( self, "backEnd01Api", rest_api_name=f"{back_end_api_name}", deploy_options=prod_api_stage_options, endpoint_types=[_apigw.EndpointType.EDGE], description= f"{GlobalArgs.OWNER}: API Best Practices. This stack deploys an API and integrates with Lambda $LATEST alias." ) wa_api_res = wa_api.root.add_resource("well-architected-api") create_content = wa_api_res.add_resource("create-content") # Add POST method to API create_content_get = create_content.add_method( http_method="POST", request_parameters={ "method.request.header.InvocationType": True, "method.request.path.mystique": True }, integration=_apigw.LambdaIntegration(handler=greeter_fn, proxy=True)) # Outputs output_0 = core.CfnOutput( self, "AutomationFrom", value=f"{GlobalArgs.SOURCE_INFO}", description= "To know more about this automation stack, check out our github page." ) output_1 = core.CfnOutput( self, "ContentCreatorApiUrl", value= f"curl -X POST -H 'Content-Type: text/plain' -d 'Hello again :)' {create_content.url}", description= 'Use an utility like curl to add content to EFS. For ex: curl -X POST -H "Content-Type: text/plain" -d "Hello again :)" ${API_URL}' )
def __init__( self, scope: core.Construct, id: str, vpc, stack_log_level: str, back_end_api_name: str, **kwargs ) -> None: super().__init__(scope, id, **kwargs) # Create Serverless Event Processor using Lambda): # Read Lambda Code): try: with open("secure_private_api/stacks/back_end/lambda_src/serverless_greeter.py", mode="r") as f: greeter_fn_code = f.read() except OSError as e: print("Unable to read Lambda Function Code") raise e greeter_fn = _lambda.Function( self, "getSquareFn", function_name=f"greeter_fn_{id}", runtime=_lambda.Runtime.PYTHON_3_7, handler="index.lambda_handler", code=_lambda.InlineCode(greeter_fn_code), timeout=core.Duration.seconds(15), reserved_concurrent_executions=1, environment={ "LOG_LEVEL": f"{stack_log_level}", "Environment": "Production", "ANDON_CORD_PULLED": "False" } ) greeter_fn_version = greeter_fn.latest_version greeter_fn_version_alias = _lambda.Alias( self, "greeterFnAlias", alias_name="MystiqueAutomation", version=greeter_fn_version ) # Create Custom Loggroup # /aws/lambda/function-name greeter_fn_lg = _logs.LogGroup( self, "squareFnLoggroup", log_group_name=f"/aws/lambda/{greeter_fn.function_name}", retention=_logs.RetentionDays.ONE_WEEK, removal_policy=core.RemovalPolicy.DESTROY ) # Add API GW front end for the Lambda back_end_01_api_stage_options = _apigw.StageOptions( stage_name="miztiik", throttling_rate_limit=10, throttling_burst_limit=100, logging_level=_apigw.MethodLoggingLevel.INFO ) # Lets create a private secure end point # Create a security group dedicated to our API Endpoint self.secure_private_api_01_sec_grp = _ec2.SecurityGroup( self, "secureApi01SecurityGroup", vpc=vpc, allow_all_outbound=True, description="Miztiik Automation: Secure our private API using security groups" ) # Allow 443 inbound on our Security Group self.secure_private_api_01_sec_grp.add_ingress_rule( _ec2.Peer.ipv4(vpc.vpc_cidr_block), _ec2.Port.tcp(443) ) secure_private_api_01_endpoint = _ec2.InterfaceVpcEndpoint( self, "secureApi01Endpoint", vpc=vpc, service=_ec2.InterfaceVpcEndpointAwsService.APIGATEWAY, private_dns_enabled=True, subnets=_ec2.SubnetSelection( subnet_type=_ec2.SubnetType.ISOLATED ) ) # Create a API Gateway Resource Policy to attach to API GW # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-restapi.html#cfn-apigateway-restapi-policy secure_private_api_01_res_policy = _iam.PolicyDocument( statements=[ _iam.PolicyStatement( principals=[_iam.AnyPrincipal()], actions=["execute-api:Invoke"], # resources=[f"{api_01.arn_for_execute_api(method="GET",path="greeter", stage="miztiik")}"], resources=[core.Fn.join("", ["execute-api:/", "*"])], effect=_iam.Effect.DENY, conditions={ "StringNotEquals": { "aws:sourceVpc": f"{secure_private_api_01_endpoint.vpc_endpoint_id}" } }, sid="DenyAllNonVPCAccessToApi" ), _iam.PolicyStatement( principals=[_iam.AnyPrincipal()], actions=["execute-api:Invoke"], resources=[core.Fn.join("", ["execute-api:/", "*"])], effect=_iam.Effect.ALLOW, sid="AllowVPCAccessToApi" ) ] ) # Create API Gateway secure_private_api_01 = _apigw.RestApi( self, "backEnd01Api", rest_api_name=f"{back_end_api_name}", deploy_options=back_end_01_api_stage_options, endpoint_types=[ _apigw.EndpointType.PRIVATE ], policy=secure_private_api_01_res_policy, ) back_end_01_api_res = secure_private_api_01.root.add_resource("secure") greeter = back_end_01_api_res.add_resource("greeter") greeter_method_get = greeter.add_method( http_method="GET", request_parameters={ "method.request.header.InvocationType": True, "method.request.path.number": True }, integration=_apigw.LambdaIntegration( handler=greeter_fn, proxy=True ) ) # Outputs output_1 = core.CfnOutput( self, "SecureApiUrl", value=f"{greeter.url}", description="Use an utility like curl from the same VPC as the API to invoke it." )
def __init__(self, scope: core.Construct, id: str, stack_log_level: str, back_end_api_name: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) # Create Serverless Event Processor using Lambda): # Read Lambda Code): try: with open( "secure_api_with_keys/stacks/back_end/lambda_src/serverless_greeter.py", mode="r") as f: greeter_fn_code = f.read() except OSError as e: print("Unable to read Lambda Function Code") raise e greeter_fn = _lambda.Function( self, "secureGreeterFn", function_name=f"greeter_fn_{id}", runtime=_lambda.Runtime.PYTHON_3_7, handler="index.lambda_handler", code=_lambda.InlineCode(greeter_fn_code), timeout=core.Duration.seconds(15), reserved_concurrent_executions=20, environment={ "LOG_LEVEL": f"{stack_log_level}", "Environment": "Production", "ANDON_CORD_PULLED": "False", "RANDOM_SLEEP_ENABLED": "False" }, description="Creates a simple greeter function") greeter_fn_version = greeter_fn.latest_version greeter_fn_version_alias = _lambda.Alias( self, "greeterFnAlias", alias_name="MystiqueAutomation", version=greeter_fn_version) # Create Custom Loggroup # /aws/lambda/function-name greeter_fn_lg = _logs.LogGroup( self, "greeterFnLoggroup", log_group_name=f"/aws/lambda/{greeter_fn.function_name}", retention=_logs.RetentionDays.ONE_WEEK, removal_policy=core.RemovalPolicy.DESTROY) # Add API GW front end for the Lambda back_end_01_api_stage_options = _apigw.StageOptions( stage_name="miztiik", throttling_rate_limit=10, throttling_burst_limit=100, # Log full requests/responses data data_trace_enabled=True, # Enable Detailed CloudWatch Metrics metrics_enabled=True, logging_level=_apigw.MethodLoggingLevel.INFO, ) # Create API Gateway secure_api_with_keys_01 = _apigw.RestApi( self, "backEnd01Api", rest_api_name=f"{back_end_api_name}", deploy_options=back_end_01_api_stage_options, endpoint_types=[_apigw.EndpointType.REGIONAL], description= f"{GlobalArgs.OWNER}: API Best Practice Demonstration - Security for APIs with Keys" ) back_end_01_api_res = secure_api_with_keys_01.root.add_resource( "secure") greeter = back_end_01_api_res.add_resource("greeter") greeter_method_get = greeter.add_method( http_method="GET", request_parameters={ "method.request.header.InvocationType": True, "method.request.path.pkon": True }, integration=_apigw.LambdaIntegration(handler=greeter_fn, proxy=True), api_key_required=True) # Start with the API Keys dev_kon_api_key = _apigw.ApiKey( self, "devApiKey", description="The Api Key for 'Kon' Developer", enabled=True, api_key_name="Developer-Kon-Key", # value ="" # Leave it to AWS to create a random key for us ) partner_api_key = _apigw.ApiKey( self, "partnerApiKey", description="The Api Key for 'Partner' Mystique Corp", enabled=True, api_key_name="Partner-Mystique-Corp-Key", ) # We have API Keys to attach to Usage Plan # Usage plan for Developer with METHOD Level throttling # There seems to be a BUG. console allows rate_limit to be float. But CDK throws an error. secure_api_with_keys_01_usage_plan_01 = secure_api_with_keys_01.add_usage_plan( "secureApiDevUsagePlan", name="DeveloperUsagePlan", api_key=dev_kon_api_key, api_stages=[ _apigw.UsagePlanPerApiStage( api=secure_api_with_keys_01, stage=secure_api_with_keys_01.deployment_stage) ], throttle=_apigw.ThrottleSettings(burst_limit=1, rate_limit=1), quota=_apigw.QuotaSettings(limit=1440, period=_apigw.Period.DAY), description= "Mystique Automation: Api Security with usage plan and throttling. Usage plan for developer s kon" ) # Usage plan for Partner with METHOD Level throttling secure_api_with_keys_01_usage_plan_02 = secure_api_with_keys_01.add_usage_plan( "secureApiPartnerUsagePlan", name="PartnerUsagePlan", api_key=partner_api_key, api_stages=[ _apigw.UsagePlanPerApiStage( api=secure_api_with_keys_01, stage=secure_api_with_keys_01.deployment_stage, throttle=[ _apigw.ThrottlingPerMethod( method=greeter_method_get, throttle=_apigw.ThrottleSettings(burst_limit=50, rate_limit=5)) ]) ], throttle=_apigw.ThrottleSettings(burst_limit=100, rate_limit=10), quota=_apigw.QuotaSettings(limit=864000, period=_apigw.Period.DAY), description= "Mystique Automation: Api Security with usage plan and throttling. Usage plan for Partner Mystique Corp" ) # Outputs output_1 = core.CfnOutput( self, "SecureApiWithKeysUrl", value=f"{greeter.url}", description= "Use an utility like curl from the same VPC as the API to invoke it." )
def __init__(self, scope: core.Construct, id: str, stack_log_level: str, back_end_api_name: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) # Create Serverless Event Processor using Lambda): # Read Lambda Code): try: with open( "api_with_stage_variables/stacks/back_end/lambda_src/serverless_greeter.py", mode="r") as f: backend_greeter_fn_code = f.read() except OSError as e: print("Unable to read Lambda Function Code") raise e backend_greeter_fn = _lambda.Function( self, "backendGreeterFn", function_name=f"greeter_fn_{id}", runtime=_lambda.Runtime.PYTHON_3_7, handler="index.lambda_handler", code=_lambda.InlineCode(backend_greeter_fn_code), timeout=core.Duration.seconds(15), reserved_concurrent_executions=20, environment={ "LOG_LEVEL": f"{stack_log_level}", "Environment": "Production", "ANDON_CORD_PULLED": "False", "RANDOM_SLEEP_ENABLED": "False" }, description= "A simple greeter function, which responds with a timestamp") backend_greeter_fn_version = backend_greeter_fn.latest_version backend_greeter_fn_version_alias = _lambda.Alias( self, "greeterFnAlias", alias_name="MystiqueAutomation", version=backend_greeter_fn_version) # Create Custom Loggroup # /aws/lambda/function-name backend_greeter_fn_lg = _logs.LogGroup( self, "greeterFnLoggroup", log_group_name=f"/aws/lambda/{backend_greeter_fn.function_name}", retention=_logs.RetentionDays.ONE_WEEK, removal_policy=core.RemovalPolicy.DESTROY) # Add API GW front end for the Lambda anti_pattern_api_stage_options = _apigw.StageOptions( stage_name="prod", throttling_rate_limit=10, throttling_burst_limit=100, logging_level=_apigw.MethodLoggingLevel.INFO) # Create API Gateway anti_pattern_api = _apigw.RestApi( self, "backEnd01Api", rest_api_name=f"{back_end_api_name}", deploy_options=anti_pattern_api_stage_options, endpoint_types=[_apigw.EndpointType.EDGE], description= f"{GlobalArgs.OWNER}: API Best Practices. This stack deploys an API and integrates with Lambda $LATEST alias, which is the default" ) anti_pattern_api_res = anti_pattern_api.root.add_resource( "anti-pattern-api") greeter = anti_pattern_api_res.add_resource("greeter") greeter_method_get = greeter.add_method( http_method="GET", request_parameters={ "method.request.header.InvocationType": True, "method.request.path.skon": True }, integration=_apigw.LambdaIntegration(handler=backend_greeter_fn, proxy=True)) # Outputs output_0 = core.CfnOutput( self, "AutomationFrom", value=f"{GlobalArgs.SOURCE_INFO}", description= "To know more about this automation stack, check out our github page." ) output_1 = core.CfnOutput( self, "AntiPatternApiUrl", value=f"{greeter.url}", description="Use a browser to access this url.")
def __init__(self, scope: cdk.Construct, construct_id: str, stack_log_level: str, store_events_topic, **kwargs) -> None: super().__init__(scope, construct_id, **kwargs) # Add your stack resources below) # Sales Queue Consumer sales_q = _sqs.Queue( self, "salesEventsQueue", delivery_delay=cdk.Duration.seconds(5), queue_name=f"sales_q", retention_period=cdk.Duration.days(2), visibility_timeout=cdk.Duration.seconds(10), receive_message_wait_time=cdk.Duration.seconds(10)) # Create a Filter for Sales Subscription sales_policy = { "evnt_type": _sns.SubscriptionFilter(conditions=["sales-event"]) } # Create an SQS type subscription to SNS sales_subs = _sns_subs.SqsSubscription(sales_q, filter_policy=sales_policy) # Add the scription to topic store_events_topic.add_subscription(sales_subs) # Read Lambda Code try: with open( "stacks/back_end/serverless_sns_consumer_stack/lambda_src/sqs_data_consumer.py", encoding="utf-8", mode="r") as f: msg_consumer_fn_code = f.read() except OSError: print("Unable to read Lambda Function Code") raise msg_consumer_fn = _lambda.Function( self, "msgConsumerFn", function_name=f"sales_queue_consumer_fn", description="Process messages in SQS queue", runtime=_lambda.Runtime.PYTHON_3_7, code=_lambda.InlineCode(msg_consumer_fn_code), handler="index.lambda_handler", timeout=cdk.Duration.seconds(5), reserved_concurrent_executions=1, environment={ "LOG_LEVEL": f"{stack_log_level}", "APP_ENV": "Production", "SALES_QUEUE_NAME": f"{sales_q.queue_name}", "TRIGGER_RANDOM_DELAY": "True" }) msg_consumer_fn_version = msg_consumer_fn.latest_version msg_consumer_fn_version_alias = _lambda.Alias( self, "msgConsumerFnAlias", alias_name="MystiqueAutomation", version=msg_consumer_fn_version) # Create Custom Loggroup for Producer msg_consumer_fn_lg = _logs.LogGroup( self, "msgConsumerFnLogGroup", log_group_name=f"/aws/lambda/{msg_consumer_fn.function_name}", removal_policy=cdk.RemovalPolicy.DESTROY, retention=_logs.RetentionDays.ONE_DAY) # Restrict Produce Lambda to be invoked only from the stack owner account msg_consumer_fn.add_permission("restrictLambdaInvocationToOwnAccount", principal=_iam.AccountRootPrincipal(), action="lambda:InvokeFunction", source_account=cdk.Aws.ACCOUNT_ID, source_arn=sales_q.queue_arn) # Set our Lambda Function to be invoked by SQS msg_consumer_fn.add_event_source(_sqsEventSource(sales_q, batch_size=5)) ########################################### ################# OUTPUTS ################# ########################################### output_0 = cdk.CfnOutput( self, "AutomationFrom", value=f"{GlobalArgs.SOURCE_INFO}", description= "To know more about this automation stack, check out our github page." ) output_2 = cdk.CfnOutput( self, "SalesEventsConsumer", value= f"https://console.aws.amazon.com/lambda/home?region={cdk.Aws.REGION}#/functions/{msg_consumer_fn.function_name}", description="Process events received from SQS event bus")
def __init__(self, scope: core.Construct, construct_id: str, stack_log_level: str, orders_bus, **kwargs) -> None: super().__init__(scope, construct_id, **kwargs) # Add your stack resources below) # Read Lambda Code try: with open( "stacks/back_end/serverless_eventbridge_consumer_stack/lambda_src/eventbridge_data_consumer.py", encoding="utf-8", mode="r") as f: msg_consumer_fn_code = f.read() except OSError: print("Unable to read Lambda Function Code") raise msg_consumer_fn = _lambda.Function( self, "msgConsumerFn", function_name=f"events_consumer_fn", description="Process messages in EventBridge queue", runtime=_lambda.Runtime.PYTHON_3_7, code=_lambda.InlineCode(msg_consumer_fn_code), handler="index.lambda_handler", timeout=core.Duration.seconds(3), reserved_concurrent_executions=1, environment={ "LOG_LEVEL": f"{stack_log_level}", "APP_ENV": "Production" }) msg_consumer_fn_version = msg_consumer_fn.latest_version msg_consumer_fn_version_alias = _lambda.Alias( self, "msgConsumerFnAlias", alias_name="MystiqueAutomation", version=msg_consumer_fn_version) # Create Custom Loggroup for Producer msg_consumer_fn_lg = _logs.LogGroup( self, "msgConsumerFnLogGroup", log_group_name=f"/aws/lambda/{msg_consumer_fn.function_name}", removal_policy=core.RemovalPolicy.DESTROY, retention=_logs.RetentionDays.ONE_DAY) # Restrict Produce Lambda to be invoked only from the stack owner account msg_consumer_fn.add_permission("restrictLambdaInvocationToOwnAccount", principal=_iam.AccountRootPrincipal(), action="lambda:InvokeFunction", source_account=core.Aws.ACCOUNT_ID, source_arn=orders_bus.event_bus_arn) # Event Pattern self.orders_pattern = _evnts.EventPattern(detail_type=["sales-events"]) # EventBridge Routing Rule self.orders_routing = _evnts.Rule( self, f"ordersEventRoutingRule01", description="A simple events routing rule", enabled=True, event_bus=orders_bus, event_pattern=self.orders_pattern, rule_name="orders_routing_to_consumer", targets=[_evnts_tgt.LambdaFunction(handler=msg_consumer_fn)]) self.orders_routing.apply_removal_policy(core.RemovalPolicy.DESTROY) # Restrict Produce Lambda to be invoked only from the stack owner account data_producer_fn.add_permission( "restrictLambdaInvocationToFhInOwnAccount", principal=_iam.AccountRootPrincipal(), action="lambda:InvokeFunction", source_account=core.Aws.ACCOUNT_ID) ########################################### ################# OUTPUTS ################# ########################################### output_0 = core.CfnOutput( self, "AutomationFrom", value=f"{GlobalArgs.SOURCE_INFO}", description= "To know more about this automation stack, check out our github page." ) output_2 = core.CfnOutput( self, "msgConsumer", value= f"https://console.aws.amazon.com/lambda/home?region={core.Aws.REGION}#/functions/{msg_consumer_fn.function_name}", description="Process events received from eventbridge event bus")
def __init__(self, scope: core.Construct, id: str, **kwargs): super().__init__(scope, id, **kwargs) # The code that defines your stack goes here this_dir = path.dirname(__file__) handler = lmb.Function(self, 'Handler', runtime=lmb.Runtime.PYTHON_3_7, handler='handler.handler', code=lmb.Code.from_asset( path.join(this_dir, 'lambda'))) alias = lmb.Alias(self, "HandlerAlias", alias_name="Current", version=handler.current_version) gw = apigw.LambdaRestApi( self, 'Gateway', description='Endpoint for a singple Lambda-powered web service', handler=alias, endpoint_types=[EndpointType.REGIONAL]) failure_alarm = cloudwatch.Alarm( self, "FailureAlarm", alarm_name=self.stack_name + '-' + '500Alarm', metric=cloudwatch.Metric(metric_name="5XXError", namespace="AWS/ApiGateway", dimensions={ "ApiName": "Gateway", }, statistic="Sum", period=core.Duration.minutes(1)), threshold=1, evaluation_periods=1) alarm500topic = sns.Topic(self, "Alarm500Topic", topic_name=self.stack_name + '-' + 'Alarm500TopicSNS') alarm500topic.add_subscription( subscriptions.EmailSubscription("*****@*****.**")) failure_alarm.add_alarm_action(cw_actions.SnsAction(alarm500topic)) codedeploy.LambdaDeploymentGroup( self, "DeploymentGroup", alias=alias, deployment_config=codedeploy.LambdaDeploymentConfig. CANARY_10_PERCENT_10_MINUTES, alarms=[failure_alarm]) # Create a dynamodb table table_name = self.stack_name + '-' + 'HelloCdkTable' table = dynamodb.Table(self, "TestTable", table_name=table_name, partition_key=Attribute( name="id", type=dynamodb.AttributeType.STRING)) table_name_id = cr.PhysicalResourceId.of(table.table_name) on_create_action = AwsSdkCall( action='putItem', service='DynamoDB', physical_resource_id=table_name_id, parameters={ 'Item': { 'id': { 'S': 'HOLA_CREATE' }, 'date': { 'S': datetime.today().strftime('%Y-%m-%d') }, 'epoch': { 'N': str(int(time.time())) } }, 'TableName': table_name }) on_update_action = AwsSdkCall( action='putItem', service='DynamoDB', physical_resource_id=table_name_id, parameters={ 'Item': { 'id': { 'S': 'HOLA_UPDATE' }, 'date': { 'S': datetime.today().strftime('%Y-%m-%d') }, 'epoch': { 'N': str(int(time.time())) } }, 'TableName': table_name }) cr.AwsCustomResource( self, "TestTableCustomResource", on_create=on_create_action, on_update=on_update_action, policy=cr.AwsCustomResourcePolicy.from_sdk_calls( resources=cr.AwsCustomResourcePolicy.ANY_RESOURCE)) # OUTPUT self.url_output = core.CfnOutput(self, 'Url', value=gw.url)
def __init__(self, scope: core.Construct, id: str, back_end_api_name: str, stack_log_level: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) # Create Lambda Destination Queue async_dest_queue = _sqs.Queue( self, "Queue", queue_name="async_get_square_fn_dest_queue") # Create Serverless Event Processor using Lambda): # Read Lambda Code): try: with open( "serverless_async_lambda_api/stacks/back_end/lambda_src/get_square.py", mode="r") as f: get_square_fn_code = f.read() except OSError as e: print("Unable to read Lambda Function Code") raise e get_square_fn = _lambda.Function( self, "getSquareFn", function_name="get_square_fn", runtime=_lambda.Runtime.PYTHON_3_7, handler="index.lambda_handler", code=_lambda.InlineCode(get_square_fn_code), timeout=core.Duration.seconds(15), reserved_concurrent_executions=1, on_success=_lambda_dest.SqsDestination(async_dest_queue), on_failure=_lambda_dest.SqsDestination(async_dest_queue), environment={ "LOG_LEVEL": f"{stack_log_level}", "Environment": "Production", "ANDON_CORD_PULLED": "False" }) get_square_fn_version = get_square_fn.latest_version get_square_fn_version_alias = _lambda.Alias( self, "greeterFnAlias", alias_name="MystiqueAutomation", version=get_square_fn_version) # Add Permissions to lambda to write messags to queue async_dest_queue.grant_send_messages(get_square_fn) # Create Custom Loggroup # /aws/lambda/function-name get_square_fn_fn_lg = _logs.LogGroup( self, "squareFnLoggroup", log_group_name=f"/aws/lambda/{get_square_fn.function_name}", retention=_logs.RetentionDays.ONE_WEEK, removal_policy=core.RemovalPolicy.DESTROY) # Add API GW front end for the Lambda back_end_01_api_stage_options = _apigw.StageOptions( stage_name="miztiik", throttling_rate_limit=10, throttling_burst_limit=100, logging_level=_apigw.MethodLoggingLevel.INFO) # Create API Gateway api_01 = _apigw.RestApi(self, "backEnd01Api", rest_api_name=f"{back_end_api_name}", deploy_options=back_end_01_api_stage_options, endpoint_types=[_apigw.EndpointType.REGIONAL]) # InvocationType='RequestResponse' if async_ else 'Event' back_end_01_api_res = api_01.root.add_resource("square") get_square = back_end_01_api_res.add_resource("{number}") # API VTL Template mapping # https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-integration-async.html # https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html # https://aws.amazon.com/premiumsupport/knowledge-center/custom-headers-api-gateway-lambda/ req_template = f'{{"number": "$input.params("number")"}}' # We are going to loop through the headers. Find the key:value for asynchrony i.e "InvocationType:Event" # If the headers are found, set is_async to true # If not found, return the response from lambda resp_template = """{ "api_stage": "$context.stage", "api_request_id": "$context.requestId", "api_resource_path": "$context.resourcePath", "http_method": "$context.httpMethod", "source_ip": "$context.identity.sourceIp", "user-agent": "$context.identity.userAgent", #set($num_square = $util.escapeJavaScript($!input.json('$.square'))) #foreach($param in $input.params().header.keySet()) #if($param == "invocationtype" or $param == "InvocationType" && $util.escapeJavaScript($input.params().header.get($param)) == "Event") #set($is_async = "true") #end #end #if($is_async == "true") "asynchronous_invocation":"true", "message":"Event received. Check queue/logs for status" #else "synchronous_invocation":"true", "square_of_your_number_is":$!{num_square} #end } """ get_square_method_get = get_square.add_method( http_method="GET", request_parameters={ "method.request.header.InvocationType": True, "method.request.path.number": True }, integration=_apigw.LambdaIntegration( handler=get_square_fn, proxy=False, request_parameters={ "integration.request.path.number": "method.request.path.number", "integration.request.header.X-Amz-Invocation-Type": "method.request.path.InvocationType", "integration.request.header.Content-Type": "'application/x-www-form-urlencoded'" }, passthrough_behavior=_apigw.PassthroughBehavior. WHEN_NO_TEMPLATES, request_templates={"application/json": f"{req_template}"}, integration_responses=[ _apigw.IntegrationResponse( status_code="200", # selection_pattern="2\d{2}", # Use for mapping Lambda Errors response_parameters={}, response_templates={ "application/json": f"{resp_template}" }) ]), method_responses=[ _apigw.MethodResponse( status_code="200", response_parameters={ "method.response.header.Content-Length": True, }, response_models={"application/json": _apigw.EmptyModel()}) ]) # Outputs output_1 = core.CfnOutput( self, "GetSquareApiUrl", value=f"{get_square.url}", description= "Use a browser to access this url. Change {number} to any value between 1 and 100." )
def __init__(self, scope: core.Construct, id: str, stack_log_level: str, back_end_api_name: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) # Read Lambda Code): try: with open( "secure_api_with_throttling/stacks/back_end/lambda_src/serverless_greeter.py", mode="r") as f: greeter_fn_code = f.read() except OSError as e: print("Unable to read Lambda Function Code") raise e greeter_fn = _lambda.Function( self, "getSquareFn", function_name=f"greeter_fn_{id}", runtime=_lambda.Runtime.PYTHON_3_7, handler="index.lambda_handler", code=_lambda.InlineCode(greeter_fn_code), timeout=core.Duration.seconds(15), reserved_concurrent_executions=100, environment={ "LOG_LEVEL": f"{stack_log_level}", "Environment": "Production", "RANDOM_SLEEP_SECS": "10", "ANDON_CORD_PULLED": "False" }, description="Creates a simple greeter function") greeter_fn_version = greeter_fn.latest_version greeter_fn_version_alias = _lambda.Alias( self, "greeterFnAlias", alias_name="MystiqueAutomation", version=greeter_fn_version) # Create Custom Loggroup greeter_fn_lg = _logs.LogGroup( self, "squareFnLoggroup", log_group_name=f"/aws/lambda/{greeter_fn.function_name}", retention=_logs.RetentionDays.ONE_WEEK, removal_policy=core.RemovalPolicy.DESTROY) # Add API GW front end for the Lambda back_end_api_stage_01_options = _apigw.StageOptions( stage_name="miztiik-throttled", throttling_rate_limit=10, throttling_burst_limit=100, logging_level=_apigw.MethodLoggingLevel.INFO) # Create API Gateway secure_api_with_throttling_01 = _apigw.RestApi( self, "backEnd01Api", rest_api_name=f"{back_end_api_name}", deploy_options=back_end_api_stage_01_options, endpoint_types=[_apigw.EndpointType.EDGE], description= f"{GlobalArgs.OWNER}: API Security Automation using - Throttling & Web Application Firewall" ) back_end_01_api_res = secure_api_with_throttling_01.root.add_resource( "secure") greeter = back_end_01_api_res.add_resource("greeter") greeter_method_get = greeter.add_method( http_method="GET", request_parameters={ "method.request.header.InvocationType": True, "method.request.path.number": True }, integration=_apigw.LambdaIntegration(handler=greeter_fn, proxy=True)) # Lets export the url to be used in load generator # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-wafv2-webaclassociation.html # arn:aws:apigateway:region::/restapis/api-id/stages/stage-name self.secure_api_stage_arn = f"arn:aws:apigateway:{core.Aws.REGION}::/restapis/{secure_api_with_throttling_01.rest_api_id}/stages/{back_end_api_stage_01_options.stage_name}" # Export the Api Url to be used in the Load generator stack self.api_url = greeter.url # Outputs output_1 = core.CfnOutput( self, "SecureApiUrl", value=f"{self.api_url}", description="Use an utility like curl to access the API.")
def __init__(self, scope: cdk.Construct, construct_id: str, stack_log_level: str, **kwargs) -> None: super().__init__(scope, construct_id, **kwargs) # Add your stack resources below): # Create SNS Topic self.store_events_topic = _sns.Topic( self, "dataTopic", display_name="MessageFilterDemoTopic", topic_name=f"store_events_{construct_id}_topic") ######################################## ####### ####### ####### Stream Data Producer ####### ####### ####### ######################################## # Read Lambda Code try: with open( "stacks/back_end/serverless_sns_producer_stack/lambda_src/stream_data_producer.py", encoding="utf-8", mode="r", ) as f: data_producer_fn_code = f.read() except OSError: print("Unable to read Lambda Function Code") raise data_producer_fn = _lambda.Function( self, "streamDataProducerFn", function_name=f"data_producer_{construct_id}", description="Produce streaming data events and push to SNS stream", runtime=_lambda.Runtime.PYTHON_3_7, code=_lambda.InlineCode(data_producer_fn_code), handler="index.lambda_handler", timeout=cdk.Duration.seconds(1), reserved_concurrent_executions=1, environment={ "LOG_LEVEL": "INFO", "APP_ENV": "Production", "MAX_MSGS_TO_PRODUCE": "5", "TOPIC_ARN": f"{self.store_events_topic.topic_arn}", "TRIGGER_RANDOM_DELAY": "True" }, ) # Grant our Lambda Producer privileges to write to SNS Data Stream self.store_events_topic.grant_publish(data_producer_fn) data_producer_fn_version = data_producer_fn.latest_version data_producer_fn_version_alias = _lambda.Alias( self, "streamDataProducerFnAlias", alias_name="MystiqueAutomation", version=data_producer_fn_version, ) # Create Custom Loggroup for Producer data_producer_lg = _logs.LogGroup( self, "streamDataProducerFnLogGroup", log_group_name=f"/aws/lambda/{data_producer_fn.function_name}", removal_policy=cdk.RemovalPolicy.DESTROY, retention=_logs.RetentionDays.ONE_DAY, ) # Restrict Produce Lambda to be invoked only from the stack owner account data_producer_fn.add_permission( "restrictLambdaInvocationToOwnAccount", principal=_iam.AccountRootPrincipal(), action="lambda:InvokeFunction", source_account=cdk.Aws.ACCOUNT_ID, source_arn=self.store_events_topic.topic_arn) ########################################### ################# OUTPUTS ################# ########################################### output_0 = cdk.CfnOutput( self, "AutomationFrom", value=f"{GlobalArgs.SOURCE_INFO}", description= "To know more about this automation stack, check out our github page.", ) output_1 = cdk.CfnOutput( self, "StoreOrdersEventsProducer", value= f"https://console.aws.amazon.com/lambda/home?region={cdk.Aws.REGION}#/functions/{data_producer_fn.function_name}", description="Produce streaming data events and push to SNS Topic.", )
def __init__(self, scope: core.Construct, id: str, stack_log_level: str, back_end_api_name: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) # Create Serverless Event Processor using Lambda): # Read Lambda Code): try: with open( "api_with_stage_variables/stacks/back_end/lambda_src/serverless_greeter.py", mode="r") as f: greeter_fn_code = f.read() except OSError as e: print("Unable to read Lambda Function Code") raise e greeter_fn = _lambda.Function( self, "secureGreeterFn", function_name=f"greeter_fn_{id}", runtime=_lambda.Runtime.PYTHON_3_7, handler="index.lambda_handler", code=_lambda.InlineCode(greeter_fn_code), timeout=core.Duration.seconds(15), reserved_concurrent_executions=20, environment={ "LOG_LEVEL": f"{stack_log_level}", "Environment": "Production", "ANDON_CORD_PULLED": "False", "RANDOM_SLEEP_ENABLED": "False" }, description= "A simple greeter function, which responds with a timestamp") greeter_fn_version = greeter_fn.latest_version greeter_fn_version_alias = _lambda.Alias( self, "greeterFnMystiqueAutomationAlias", alias_name="MystiqueAutomation", version=greeter_fn_version) greeter_fn_dev_alias = _lambda.Alias(self, "greeterFnDevAlias", alias_name="dev", version=greeter_fn_version) greeter_fn_test_alias = _lambda.Alias(self, "greeterFnTestAlias", alias_name="test", version=greeter_fn_version) greeter_fn_prod_alias = _lambda.Alias(self, "greeterFnProdAlias", alias_name="prod", version=greeter_fn_version) # Create Custom Loggroup # /aws/lambda/function-name greeter_fn_lg = _logs.LogGroup( self, "greeterFnLoggroup", log_group_name=f"/aws/lambda/{greeter_fn.function_name}", retention=_logs.RetentionDays.ONE_WEEK, removal_policy=core.RemovalPolicy.DESTROY) # %% # Create API Gateway wa_api = _apigw.RestApi( self, "backEnd01Api", rest_api_name=f"{back_end_api_name}", # deploy_options=wa_api_dev_stage_options, retain_deployments=False, deploy=False, endpoint_types=[_apigw.EndpointType.EDGE], description= f"{GlobalArgs.OWNER}: API Best Practices. Stage Variables for APIs. This stack deploys an API and integrates with Lambda using Stage Variables." ) wa_api_logs = _logs.LogGroup( self, "waApiLogs", log_group_name=f"/aws/apigateway/{back_end_api_name}/access_logs", removal_policy=core.RemovalPolicy.DESTROY, retention=_logs.RetentionDays.ONE_DAY) ###################################### ## CONFIG FOR API STAGE : DEV ## ###################################### dev_wa_api_deploy = _apigw.Deployment( self, "devDeploy", api=wa_api, description=f"{GlobalArgs.OWNER}: Deployment of 'dev' Api Stage", retain_deployments=False) dev_api_stage = _apigw.Stage( self, "devStage", deployment=dev_wa_api_deploy, stage_name="miztiik-dev", throttling_rate_limit=10, throttling_burst_limit=100, # Log full requests/responses data data_trace_enabled=True, # Enable Detailed CloudWatch Metrics metrics_enabled=True, logging_level=_apigw.MethodLoggingLevel.INFO, access_log_destination=_apigw.LogGroupLogDestination(wa_api_logs), variables={"lambdaAlias": "dev"}) # wa_api.deployment_stage = dev_api_stage test_wa_api_deploy = _apigw.Deployment( self, "testDeploy", api=wa_api, description=f"{GlobalArgs.OWNER}: Deployment of 'test' Api Stage", retain_deployments=False) test_api_stage = _apigw.Stage( self, "testStage", deployment=test_wa_api_deploy, stage_name="miztiik-test", throttling_rate_limit=10, throttling_burst_limit=100, # Log full requests/responses data data_trace_enabled=True, # Enable Detailed CloudWatch Metrics metrics_enabled=True, logging_level=_apigw.MethodLoggingLevel.INFO, access_log_destination=_apigw.LogGroupLogDestination(wa_api_logs), variables={"lambdaAlias": "test"}) wa_api.deployment_stage = test_api_stage prod_wa_api_deploy = _apigw.Deployment( self, "prodDeploy", api=wa_api, description=f"{GlobalArgs.OWNER}: Deployment of 'prod' Api Stage", retain_deployments=False) prod_api_stage = _apigw.Stage( self, "prodStage", deployment=prod_wa_api_deploy, stage_name="miztiik-prod", throttling_rate_limit=10, throttling_burst_limit=100, # Log full requests/responses data data_trace_enabled=True, # Enable Detailed CloudWatch Metrics metrics_enabled=True, logging_level=_apigw.MethodLoggingLevel.INFO, access_log_destination=_apigw.LogGroupLogDestination(wa_api_logs), variables={"lambdaAlias": "prod"}) prod_api_stage.node.add_dependency(test_api_stage) wa_api.deployment_stage = prod_api_stage wa_api_res = wa_api.root.add_resource("wa-api") greeter = wa_api_res.add_resource("greeter") backend_stage_uri = (f"arn:aws:apigateway:" f"{core.Aws.REGION}" f":lambda:path/2015-03-31/functions/" f"{greeter_fn.function_arn}" f":" f"${{stageVariables.lambdaAlias}}" f"/invocations") greeter_method_get = greeter.add_method( http_method="GET", request_parameters={ "method.request.header.InvocationType": True, "method.request.path.mystique": True }, # integration=_apigw.LambdaIntegration( # # handler=greeter_fn, # handler=backend_stage_uri, # proxy=True # ) integration=_apigw.Integration( type=_apigw.IntegrationType.AWS_PROXY, integration_http_method="GET", uri=backend_stage_uri)) # "arn:aws:apigateway:eu-west-2:lambda:path/2015-03-31/functions/arn:aws:lambda:eu-west-2:614517326458:function:${stageVariables.preflightFunction}/invocations", # https://lambda.us-east-1.amazonaws.com/2015-03-31/functions/arn:aws:lambda:us-east-1:230023004178:function:greeter_fn_well-architected-api:${stageVariable.lambdaAlias}/invocations # We need to manually add permissions for the stages to invoke # CDK By default adds permission only for the last .deployment_stage ##################################################################### ## CDK BUG: CONDITIONS DOES NOT TAKE EFFECT IN SERVICE PRINCIPAL ## ##################################################################### """ greeter_fn.grant_invoke( _iam.ServicePrincipal( service="apigateway.amazonaws.com", conditions={ "ArnLike": {"aws:SourceArn": "this-does-not-work"} } ) ) """ greeter_fn.add_permission( "allowStageInvocation", principal=_iam.ServicePrincipal("apigateway.amazonaws.com"), # source_arn=f"arn:aws:execute-api:{core.Aws.REGION}:{core.Aws.ACCOUNT_ID}:{wa_api.rest_api_id}/{dev_api_stage.stage_name}/{greeter_method_get.resource.path}" source_arn=greeter_method_get.method_arn.replace( wa_api.deployment_stage.stage_name, "*"), action="lambda:InvokeFunction", ) greeter_fn_dev_alias.add_permission( "greeter_fn_devAliasApiPerms", principal=_iam.ServicePrincipal("apigateway.amazonaws.com"), action="lambda:InvokeFunction", source_arn=greeter_method_get.method_arn.replace( wa_api.deployment_stage.stage_name, "*"), ) greeter_fn_test_alias.add_permission( "greeter_fn_testAliasApiPerms", principal=_iam.ServicePrincipal("apigateway.amazonaws.com"), action="lambda:InvokeFunction", source_arn=greeter_method_get.method_arn.replace( wa_api.deployment_stage.stage_name, "*"), ) greeter_fn_prod_alias.add_permission( "greeter_fn_prodAliasApiPerms", principal=_iam.ServicePrincipal("apigateway.amazonaws.com"), action="lambda:InvokeFunction", source_arn=greeter_method_get.method_arn.replace( wa_api.deployment_stage.stage_name, "*"), ) # Outputs output_0 = core.CfnOutput( self, "AutomationFrom", value=f"{GlobalArgs.SOURCE_INFO}", description= "To know more about this automation stack, check out our github page." ) output_1 = core.CfnOutput( self, "WaApiUrl", value=f"{greeter.url}", description= "Use an utility like curl from the same VPC as the API to invoke it." )
def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) # The code that defines your stack goes here lambda_policies = [ iam.PolicyStatement(actions=[ "logs:CreateLogStream", "logs:PutLogEvents", "logs:CreateLogGroup" ], effect=iam.Effect.ALLOW, resources=[ "arn:aws:logs:" + core.Aws.REGION + ":" + core.Aws.ACCOUNT_ID + ":*" ]), iam.PolicyStatement(actions=["dynamodb:*"], effect=iam.Effect.ALLOW, resources=[ "arn:aws:dynamodb:" + core.Aws.REGION + ":" + core.Aws.ACCOUNT_ID + ":*" ]) ] table = _dynamodb.Table( self, 'VisitTable', partition_key={ 'name': 'id', 'type': _dynamodb.AttributeType.STRING }, removal_policy=core.RemovalPolicy.DESTROY, read_capacity=5, write_capacity=5, ) # Modify the config.js with CF custome resource modify_policy = [ iam.PolicyStatement(actions=["dynamodb:*"], effect=iam.Effect.ALLOW, resources=[ "arn:aws:dynamodb:" + core.Aws.REGION + ":" + core.Aws.ACCOUNT_ID + ":*" ]) ] resource = _cfn.CustomResource( self, "VisitDataImportCustomResource", provider=_cfn.CustomResourceProvider.lambda_( _lambda.SingletonFunction( self, "CustomResourceSingleton", uuid="f7d4f730-4ee1-11e8-9c2d-fa7ae01bbebc", code=self.custom_resource, handler="index.handler", timeout=core.Duration.seconds(300), runtime=_lambda.Runtime.PYTHON_3_7, initial_policy=modify_policy)), properties={"DynamoDBTable": table.table_name}) base_lambda = _lambda.Function( self, 'ApiPetclinicVisitLambda', handler= 'org.springframework.samples.petclinic.visits.StreamLambdaHandler::handleRequest', runtime=_lambda.Runtime.JAVA_8, code=self.lambda_code, memory_size=1024, timeout=core.Duration.seconds(300), initial_policy=lambda_policies, environment={ "DYNAMODB_TABLE_NAME": table.table_name, "SERVER_SERVLET_CONTEXT_PATH": "/api/visit" }) version = base_lambda.add_version(str(round(time.time()))) alias = _lambda.Alias(self, 'ApiPetclinicVisitLambdaAlias', alias_name='Prod', version=version, provisioned_concurrent_executions=5) _deploy.LambdaDeploymentGroup( self, 'ApiPetclinicVisitDeploymentGroup', alias=alias, deployment_config=_deploy.LambdaDeploymentConfig. LINEAR_10_PERCENT_EVERY_1_MINUTE)
def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) # The code that defines your stack goes here # create s3 bucket bucket = _s3.Bucket(self, self.project_name + "s3bucket") test_lambda = _lambda.Function( self, 'TestHandler', runtime=_lambda.Runtime.PYTHON_3_7, code=_lambda.Code.asset('lambda'), handler='test.handler', ) test_date_lambda = _lambda.Function(self, 'TestdateHandler', runtime=_lambda.Runtime.PYTHON_3_7, code=_lambda.Code.asset('lambda'), handler='testdate.handler', layers=[ self.create_dependencies_layer( self.project_name, "testdate") ]) now = datetime.datetime.now() iso_time = now.strftime("%Y-%m-%dT%H:%M:%SZ") version = test_lambda.add_version(iso_time) alias = _lambda.Alias(self, "TestHandlerAlias", alias_name="dev", version=version) api = apigw.RestApi( self, self.project_name + "test_api", default_cors_preflight_options={ "allow_origins": apigw.Cors.ALL_ORIGINS, "allow_methods": apigw.Cors.ALL_METHODS }, #deploy=False ) api.root.add_resource("hello").add_method( "GET", apigw.LambdaIntegration(alias)) api.root.add_resource("date").add_method( "GET", apigw.LambdaIntegration(test_date_lambda)) with open('resources/api_stack.json', 'r') as myfile: data = myfile.read() # parse file api_stack = json.loads(data) for item in api_stack: current_resource = api.root for _resource in item['path'].split(os.sep): if current_resource.get_resource(_resource): current_resource = current_resource.get_resource(_resource) else: current_resource = current_resource.add_resource(_resource) _api_lambda = _lambda.Function( self, item['lambda'], runtime=_lambda.Runtime.PYTHON_3_7, code=_lambda.Code.asset("lambda/" + item['lambda'] + '.zip'), handler='main.handler', ) bucket.grant_read_write(_api_lambda) _version = _api_lambda.add_version( datetime.datetime.now().strftime("%Y-%m-%dT%H:%M:%SZ")) _alias = _lambda.Alias(self, item['lambda'] + "Alias", alias_name="dev", version=_version) _api_lambda.add_environment("BUCKET_NAME", bucket.bucket_name) current_resource.add_method(item['method'], apigw.LambdaIntegration(_alias))