示例#1
0
    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)
示例#2
0
    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,
     )
示例#4
0
    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)])
示例#5
0
    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
示例#7
0
    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
        )
示例#9
0
    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,
        )
示例#12
0
    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,
        )
示例#13
0
    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."
        )
示例#14
0
    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.")
示例#15
0
    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}'
        )
示例#19
0
    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."
        )
示例#20
0
    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."
        )
示例#21
0
    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")
示例#24
0
    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.",
        )
示例#28
0
    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)
示例#30
0
    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))