Exemplo n.º 1
0
    def __init__(self, scope: core.Construct, id: str, *, prefix: str,
                 environment: str, configuration, **kwargs):
        """
        :param scope: Stack class, used by CDK.
        :param id: ID of the construct, used by CDK.
        :param prefix: Prefix of the construct, used for naming purposes.
        :param environment: Environment of the construct, used for naming purposes.
        :param configuration: Configuration of the construct. In this case SNS_CONFIG_SCHEMA.
        :param kwargs: Other parameters that could be used by the construct.
        """
        super().__init__(scope, id, **kwargs)
        self.prefix = prefix
        self.environment_ = environment
        self._configuration = configuration

        # Validating that the payload passed is correct
        validate_configuration(configuration_schema=S3_LAMBDA_CONFIG_SCHEMA,
                               configuration_received=self._configuration)

        # Defining S3 Bucket
        bucket_data = deepcopy(self._configuration["bucket"])
        self._s3_bucket = base_bucket(self, **bucket_data)

        # Validating Lambda Function Runtime
        functions_data = self._configuration["lambda_handler"]
        self._lambda_function = base_lambda_function(self, **functions_data)

        # Defining the Lambda subscription to the specified S3 Bucket in cdk.json file.
        s3_events = self._configuration["events"]
        event_list = enum_parsing(source_list=s3_events,
                                  target_enum=s3.EventType)

        s3_subscription = events.S3EventSource(bucket=self._s3_bucket,
                                               events=event_list)
        self._lambda_function.add_event_source(source=s3_subscription)
Exemplo n.º 2
0
    def __init__(self, scope: core.Construct, id: str, *, prefix: str,
                 environment: str, configuration, **kwargs):
        """
        :param scope: Stack class, used by CDK.
        :param id: ID of the construct, used by CDK.
        :param prefix: Prefix of the construct, used for naming purposes.
        :param environment: Environment of the construct, used for naming purposes.
        :param configuration: Configuration of the construct. In this case APIGATEWAY_FAN_OUT_SCHEMA.
        :param kwargs: Other parameters that could be used by the construct.
        """
        super().__init__(scope, id, **kwargs)
        self.prefix = prefix
        self.environment_ = environment
        self._configuration = configuration

        # Validating that the payload passed is correct
        validate_configuration(configuration_schema=S3_BUCKETS_CLUSTER_SCHEMA,
                               configuration_received=self._configuration)

        # Define S3 Buckets Cluster
        self._s3_buckets = list()
        for bucket in self._configuration["buckets"]:
            _bucket = base_bucket(self, **bucket)
            self._s3_buckets.append(_bucket)
    def __init__(self, scope: core.Construct, id: str, *, prefix: str,
                 environment: str, configuration, **kwargs):
        """
        :param scope: Stack class, used by CDK.
        :param id: ID of the construct, used by CDK.
        :param prefix: Prefix of the construct, used for naming purposes.
        :param environment: Environment of the construct, used for naming purposes.
        :param configuration: Configuration of the construct. In this case APIGATEWAY_LAMBDA_SIMPLE_WEB_SERVICE_SCHEMA.
        :param kwargs: Other parameters that could be used by the construct.
        """
        super().__init__(scope, id, **kwargs)
        self.prefix = prefix
        self.environment_ = environment
        self._configuration = configuration

        # Validating that the payload passed is correct
        validate_configuration(
            configuration_schema=APIGATEWAY_SIMPLE_WEB_SERVICE_SCHEMA,
            configuration_received=self._configuration)

        # Define S3 Buckets Cluster
        if isinstance(self._configuration.get("buckets"), list):
            self._s3_buckets = [
                base_bucket(self, **bucket)
                for bucket in self._configuration["buckets"]
            ]

        api_configuration = self._configuration["api"]

        # Define Lambda Authorizer Function
        authorizer_functions = api_configuration.get("authorizer_function")
        self._authorizer_function = None
        if authorizer_functions is not None:
            if authorizer_functions.get("imported") is not None:
                self._authorizer_function = lambda_.Function.from_function_arn(
                    self,
                    id=authorizer_functions.get("imported").get("identifier"),
                    function_arn=authorizer_functions.get("imported").get(
                        "arn"),
                )
            elif authorizer_functions.get("origin") is not None:
                self._authorizer_function = base_lambda_function(
                    self, **authorizer_functions.get("origin"))

        # Define API Gateway Authorizer
        gateway_authorizer = None
        if self._authorizer_function is not None:
            # Define Gateway Token Authorizer
            authorizer_name = api_configuration[
                "apigateway_name"] + "_" + "authorizer"
            if authorizer_functions.get("results_cache_ttl") is not None:
                results_cache_ttl = core.Duration.minutes(
                    authorizer_functions.get("results_cache_ttl"))
            else:
                results_cache_ttl = None
            gateway_authorizer = api_gateway.TokenAuthorizer(
                self,
                id=authorizer_name,
                authorizer_name=authorizer_name,
                handler=self._authorizer_function,
                results_cache_ttl=results_cache_ttl)

        # Defining Custom Domain
        domain_options = None
        custom_domain = api_configuration["root_resource"].get("custom_domain")
        if custom_domain is not None:
            domain_name = custom_domain["domain_name"]
            certificate_arn = custom_domain["certificate_arn"]
            domain_options = api_gateway.DomainNameOptions(
                certificate=cert_manager.Certificate.from_certificate_arn(
                    self, id=domain_name, certificate_arn=certificate_arn),
                domain_name=domain_name,
            )

        # Define API Gateway Lambda Handler
        self._handler_function = base_lambda_function(
            self, **api_configuration["root_resource"]["handler"])

        if api_configuration["proxy"] is False and api_configuration.get(
                "root_resource").get("methods") is None:
            print(
                "Unable to check which method to use for the API! Use proxy: True or define methods..."
            )
            raise RuntimeError

        self._lambda_rest_api = api_gateway.LambdaRestApi(
            self,
            id=api_configuration["apigateway_name"],
            rest_api_name=api_configuration["apigateway_name"],
            description=api_configuration["apigateway_description"],
            domain_name=domain_options,
            handler=self._handler_function,
            proxy=api_configuration["proxy"],
            cloud_watch_role=True,
        )

        # Add Custom responses
        self._lambda_rest_api.add_gateway_response(
            f"{self.prefix}_4XXresponse_{self.environment_}",
            type=api_gateway.ResponseType.DEFAULT_4_XX,
            response_headers={"Access-Control-Allow-Origin": "'*'"},
        )
        self._lambda_rest_api.add_gateway_response(
            f"{self.prefix}_5XXresponse_{self.environment_}",
            type=api_gateway.ResponseType.DEFAULT_5_XX,
            response_headers={"Access-Control-Allow-Origin": "'*'"},
        )

        # Define Gateway Resource and Methods
        resource = self._lambda_rest_api.root.add_resource(
            api_configuration["root_resource"]["name"])
        allowed_origins = api_configuration["root_resource"].get(
            "allowed_origins")
        if api_configuration["proxy"] is False:
            gateway_methods = api_configuration["root_resource"]["methods"]
            for method in gateway_methods:
                resource.add_method(http_method=method,
                                    authorizer=gateway_authorizer)

            if allowed_origins is not None:
                resource.add_cors_preflight(allow_origins=allowed_origins,
                                            allow_methods=gateway_methods)
        else:
            if allowed_origins is not None:
                resource.add_cors_preflight(allow_origins=allowed_origins)
    def __init__(self, scope: core.Construct, id: str, *, prefix: str,
                 environment: str, configuration, **kwargs):
        """
        :param scope: Stack class, used by CDK.
        :param id: ID of the construct, used by CDK.
        :param prefix: Prefix of the construct, used for naming purposes.
        :param environment: Environment of the construct, used for naming purposes.
        :param configuration: Configuration of the construct. In this case APIGATEWAY_LAMBDA_SIMPLE_WEB_SERVICE_SCHEMA.
        :param kwargs: Other parameters that could be used by the construct.
        """
        super().__init__(scope, id, **kwargs)
        self.prefix = prefix
        self.environment_ = environment
        self._configuration = configuration

        # Validating that the payload passed is correct
        validate_configuration(
            configuration_schema=APIGATEWAY_ASYNC_WEB_SERVICE_SCHEMA,
            configuration_received=self._configuration)
        # Define S3 Buckets Cluster
        if isinstance(self._configuration.get("buckets"), list):
            self._s3_buckets = [
                base_bucket(self, **bucket)
                for bucket in self._configuration["buckets"]
            ]

        api_configuration = self._configuration["api"]

        # Define Lambda Authorizer Function
        authorizer_functions = api_configuration.get("authorizer_function")
        self._authorizer_function = None
        if authorizer_functions is not None:
            if authorizer_functions.get("imported") is not None:
                self._authorizer_function = lambda_.Function.from_function_arn(
                    self,
                    id=authorizer_functions.get("imported").get("identifier"),
                    function_arn=authorizer_functions.get("imported").get(
                        "arn"),
                )
            elif authorizer_functions.get("origin") is not None:
                self._authorizer_function = base_lambda_function(
                    self, **authorizer_functions.get("origin"))

        # Define NEW-FUNCTION Lambda Authorizers
        for lambda_function in authorizer_functions["origin"]:
            try:
                function_runtime = getattr(lambda_.Runtime,
                                           lambda_function["runtime"])
            except Exception:
                raise WrongRuntimePassed(
                    detail=
                    f"Wrong function runtime {lambda_function['runtime']} specified",
                    tb=traceback.format_exc())

            obtainer_code_path = lambda_function.get("code_path")
            if obtainer_code_path is not None:
                code_path = obtainer_code_path
            elif obtainer_code_path is None and DEFAULT_LAMBDA_CODE_PATH_EXISTS is True:
                code_path = DEFAULT_LAMBDA_CODE_PATH
            else:
                raise RuntimeError(
                    f"Code path for Lambda Function {lambda_function['lambda_name']} is not valid!"
                )

            # Defining Lambda function
            _lambda_function = lambda_.Function(
                self,
                id=self.prefix + "_" + lambda_function["lambda_name"] +
                "_lambda_" + self.environment_,
                function_name=self.prefix + "_" +
                lambda_function["lambda_name"] + "_lambda_" +
                self.environment_,
                code=lambda_.Code.from_asset(path=code_path),
                handler=lambda_function["handler"],
                runtime=function_runtime,
                layers=None,
                description=lambda_function.get("description"),
                tracing=lambda_.Tracing.ACTIVE,
                environment=lambda_function.get("environment_vars"),
                timeout=core.Duration.seconds(lambda_function.get("timeout")),
                reserved_concurrent_executions=lambda_function.get(
                    "reserved_concurrent_executions"),
            )

            # Defining Lambda Function IAM policies to access other services
            self.iam_policies = list()
            for iam_actions in configuration["iam_actions"]:
                self.iam_policies.append(iam_actions)

            policy_statement = iam.PolicyStatement(actions=self.iam_policies,
                                                   resources=["*"])
            _lambda_function.add_to_role_policy(statement=policy_statement)
            self._authorizer_lambda_functions.append(_lambda_function)
    def __init__(self, scope: core.Construct, id: str, *, prefix: str, environment: str, configuration, **kwargs):
        """
        :param scope: Stack class, used by CDK.
        :param id: ID of the construct, used by CDK.
        :param prefix: Prefix of the construct, used for naming purposes.
        :param environment: Environment of the construct, used for naming purposes.
        :param configuration: Configuration of the construct. In this case APIGATEWAY_FAN_OUT_SCHEMA.
        :param kwargs: Other parameters that could be used by the construct.
        """
        super().__init__(scope, id, **kwargs)
        self.prefix = prefix
        self.environment_ = environment
        self._configuration = configuration

        # Validating that the payload passed is correct
        validate_configuration(
            configuration_schema=S3_SPA_SIMPLE_PIPELINE_HOSTING_SCHEMA, configuration_received=self._configuration
        )

        self._deployment_bucket = base_bucket(self, **self._configuration["hosting"]["bucket"])

        artifact_bucket_name = (
            f"{self.prefix}-{self._configuration['hosting']['bucket']['bucket_name']}-artifacts-{self.environment_}"
        )
        artifact_bucket_config = {"bucket_name": artifact_bucket_name, "versioned": True, "public_read_access": False}
        self._deployment_artifact_bucket = base_bucket(self, **artifact_bucket_config)

        behaviour = cf.Behavior(
            is_default_behavior=self._configuration["hosting"]["cloudfront_distribution"]["origin_config"]["behaviours"][
                "is_default_behavior"
            ]
        )
        cloudfront_origins = cf.SourceConfiguration(
            behaviors=[behaviour], s3_origin_source=cf.S3OriginConfig(s3_bucket_source=self._deployment_bucket)
        )
        self._cloudfront_distribution = cf.CloudFrontWebDistribution(
            self,
            id=self._configuration["hosting"]["cloudfront_distribution"]["name"],
            origin_configs=[cloudfront_origins],
        )

        code_build_project_name = (
            f"{self.prefix}-{self._configuration['pipeline']['stages']['build']['name']}-cbproject-{self.environment_}"
        )
        self._codebuild_project = cb.Project(
            self,
            id=code_build_project_name,
            project_name=code_build_project_name,
            build_spec=cb.BuildSpec.from_object(
                {
                    "version": self._configuration["pipeline"]["stages"]["build"].get("version", "0.2"),
                    "phases": {"build": {"commands": self._configuration["pipeline"]["stages"]["build"]["commands"]}},
                    "artifacts": {
                        "base-directory": self._configuration["pipeline"]["stages"]["build"]["build_directory"],
                        "files": self._configuration["pipeline"]["stages"]["build"].get("files", "**/*"),
                    },
                }
            ),
        )

        source_artifact = cp.Artifact(artifact_name="source_artifact")
        single_page_app_artifact = cp.Artifact(artifact_name="single_page_app_artifact")

        pipeline_name = f"{self.prefix}-{self._configuration['pipeline']['name']}-pipeline-{self.environment_}"
        self._s3_single_page_app_pipeline = cp.Pipeline(
            self,
            id=pipeline_name,
            pipeline_name=pipeline_name,
            artifact_bucket=self._deployment_artifact_bucket,
        )

        self._s3_single_page_app_pipeline.add_stage(
            stage_name=self._configuration["pipeline"]["stages"]["github_source"]["name"],
            actions=[
                cp_actions.GitHubSourceAction(
                    action_name=self._configuration["pipeline"]["stages"]["github_source"]["name"],
                    repo=self._configuration["pipeline"]["stages"]["github_source"]["repo"],
                    owner=self._configuration["pipeline"]["stages"]["github_source"]["owner"],
                    branch=self._configuration["pipeline"]["stages"]["github_source"]["branch"],
                    oauth_token=core.SecretValue.secrets_manager(
                        secret_id=self._configuration["pipeline"]["stages"]["github_source"]["oauth_token_secret_arn"],
                    ),
                    output=source_artifact,
                )
            ],
        )

        self._s3_single_page_app_pipeline.add_stage(
            stage_name=self._configuration["pipeline"]["stages"]["build"]["name"],
            actions=[
                cp_actions.CodeBuildAction(
                    action_name=self._configuration["pipeline"]["stages"]["build"]["name"],
                    input=source_artifact,
                    project=self._codebuild_project,
                    outputs=[single_page_app_artifact],
                )
            ],
        )

        self._s3_single_page_app_pipeline.add_stage(
            stage_name=self._configuration["pipeline"]["stages"]["deploy"]["name"],
            actions=[
                cp_actions.S3DeployAction(
                    action_name=self._configuration["pipeline"]["stages"]["deploy"]["name"],
                    bucket=self._deployment_bucket,
                    input=single_page_app_artifact,
                )
            ],
        )
Exemplo n.º 6
0
    def __init__(self, scope: core.Construct, id: str, *, prefix: str, environment: str, configuration, **kwargs):
        """
        :param scope: Stack class, used by CDK.
        :param id: ID of the construct, used by CDK.
        :param prefix: Prefix of the construct, used for naming purposes.
        :param environment: Environment of the construct, used for naming purposes.
        :param configuration: Configuration of the construct. In this case SNS_CONFIG_SCHEMA.
        :param kwargs: Other parameters that could be used by the construct.
        """
        super().__init__(scope, id, **kwargs)
        self.prefix = prefix
        self.environment_ = environment
        self._configuration = configuration

        # Validating that the payload passed is correct
        validate_configuration(configuration_schema=USER_SERVERLESS_BACKEND_SCHEMA, configuration_received=self._configuration)

        # Define Lambda Authorizer Function
        authorizer_functions = self._configuration.get("authorizer_function")
        self._authorizer_function = None
        if authorizer_functions is not None:
            if authorizer_functions.get("imported") is not None:
                self._authorizer_function = lambda_.Function.from_function_arn(
                    self,
                    id=authorizer_functions.get("imported").get("identifier"),
                    function_arn=authorizer_functions.get("imported").get("arn"),
                )
            elif authorizer_functions.get("origin") is not None:
                self._authorizer_function = base_lambda_function(self, **authorizer_functions.get("origin"))

        # Define DynamoDB Tables
        self._dynamodb_tables_lambda_functions = list()
        for table in self._configuration.get("dynamo_tables", []):
            table, stream = base_dynamodb_table(self, **table)
            stream_lambda = None
            if stream is True and table["stream"].get("function") is not None:
                stream_lambda = base_lambda_function(self, **table["stream"]["function"])

                # Add DynamoDB Stream Trigger to Lambda Function
                stream_lambda.add_event_source(
                    source=event_sources.DynamoEventSource(
                        table=table, starting_position=lambda_.StartingPosition.TRIM_HORIZON, batch_size=1
                    )
                )

            self._dynamodb_tables_lambda_functions.append({"table": table, "stream_lambda": stream_lambda})

        # Define S3 Buckets Cluster
        if isinstance(self._configuration.get("buckets"), list):
            self._s3_buckets = [base_bucket(self, **bucket) for bucket in self._configuration["buckets"]]

        # Define Cognito User Pool
        user_pool_config = self._configuration["user_pool"]
        self._user_pool, self._user_pool_client = base_cognito_user_pool(self, **user_pool_config)

        if user_pool_config.get("identity_pool") is not None and self._user_pool_client is not None:
            self._identity_pool = base_cognito_user_identity_pool(
                self,
                user_pool_client_id=self._user_pool_client.user_pool_client_id,
                user_pool_provider_name=self._user_pool.user_pool_provider_name,
                **user_pool_config["identity_pool"],
            )
Exemplo n.º 7
0
    def __init__(self, scope: core.Construct, id: str, *, prefix: str,
                 environment: str, configuration, **kwargs):
        """
        :param scope: Stack class, used by CDK.
        :param id: ID of the construct, used by CDK.
        :param prefix: Prefix of the construct, used for naming purposes.
        :param environment: Environment of the construct, used for naming purposes.
        :param configuration: Configuration of the construct. In this case APIGATEWAY_LAMBDA_SIMPLE_WEB_SERVICE_SCHEMA.
        :param kwargs: Other parameters that could be used by the construct.
        """
        super().__init__(scope, id, **kwargs)
        self.prefix = prefix
        self.environment_ = environment
        self._configuration = configuration

        # Validating that the payload passed is correct
        validate_configuration(
            configuration_schema=APIGATEWAY_ROBUST_WEB_SERVICE_SCHEMA,
            configuration_received=self._configuration)
        # Define S3 Buckets Cluster
        if isinstance(self._configuration.get("buckets"), list):
            self._s3_buckets = [
                base_bucket(self, **bucket)
                for bucket in self._configuration["buckets"]
            ]

        api_configuration = self._configuration["api"]
        api_gateway_name = self.prefix + "_" + api_configuration[
            "apigateway_name"] + "_" + self.environment_
        api_gateway_name_description = api_configuration.get(
            "apigateway_description")

        # # Define Lambda Authorizer Function
        # authorizer_functions = api_configuration.get("authorizer_function")
        # self._authorizer_function = None
        # if authorizer_functions is not None:
        #     if authorizer_functions.get("imported") is not None:
        #         self._authorizer_function = lambda_.Function.from_function_arn(
        #             self,
        #             id=authorizer_functions.get("imported").get("identifier"),
        #             function_arn=authorizer_functions.get("imported").get("arn"),
        #         )
        #     elif authorizer_functions.get("origin") is not None:
        #         self._authorizer_function = base_lambda_function(self, **authorizer_functions.get("origin"))
        #
        # # Define API Gateway Authorizer
        # gateway_authorizer = None
        # if self._authorizer_function is not None:
        #     # Define Gateway Token Authorizer
        #     authorizer_name = api_configuration["apigateway_name"] + "_" + "authorizer"
        #     if authorizer_functions.get("results_cache_ttl") is not None:
        #         results_cache_ttl = core.Duration.minutes(authorizer_functions.get("results_cache_ttl"))
        #     else:
        #         results_cache_ttl = None
        #     gateway_authorizer = api_gateway.TokenAuthorizer(
        #         self,
        #         id=authorizer_name,
        #         authorizer_name=authorizer_name,
        #         handler=self._authorizer_function,
        #         results_cache_ttl=results_cache_ttl
        #     )
        #
        #     api_gateway.TokenAuthorizer
        #     api_gateway.RequestAuthorizer
        #     api_gateway.CognitoUserPoolsAuthorizer

        # Define API Gateway Authorizer
        self._authorizer_function = None
        self._gateway_authorizer = self.set_authorizer()

        # Defining Custom Domain
        domain_options = None
        custom_domain = api_configuration["settings"].get("custom_domain")
        if custom_domain is not None:
            domain_name = custom_domain["domain_name"]
            certificate_arn = custom_domain["certificate_arn"]
            domain_options = api_gateway.DomainNameOptions(
                certificate=cert_manager.Certificate.from_certificate_arn(
                    self, id=domain_name, certificate_arn=certificate_arn),
                domain_name=domain_name,
            )

        # Define API Gateway Lambda Handler
        self._handler_function = base_lambda_function(
            self, **api_configuration["settings"]["default_handler"])

        # Validating Proxy configuration for API Gateway
        proxy_configuration = api_configuration["settings"]["proxy"]
        if proxy_configuration is False and api_configuration["settings"].get(
                "default_http_methods") is None:
            print(
                "Unable to check which method to use for the API! Use proxy: True or define methods..."
            )
            raise RuntimeError

        # Defining allowed binary media types by API Gateway
        binary_media_types = api_configuration["settings"].get(
            "default_media_types")

        # Defining CORS preflight options
        default_cors_options = None
        default_cors_configuration = api_configuration["settings"].get(
            "default_cors_options")
        if default_cors_configuration is not None:
            default_cors_options = api_gateway.CorsOptions(
                allow_origins=default_cors_configuration["allow_origins"],
                allow_methods=["ANY"],
                status_code=default_cors_configuration["options_status_code"],
            )

        # Defining STAGE Options
        default_stage_options = None
        default_stage_configuration = api_configuration["settings"].get(
            "default_stage_options")
        if default_stage_configuration is not None:
            logging_level = api_gateway.MethodLoggingLevel.ERROR
            logging_level_configuration = default_stage_configuration[
                "logging_level"]
            for element in api_gateway.MethodLoggingLevel:
                if logging_level_configuration in str(element):
                    logging_level = element
            default_stage_options = api_gateway.StageOptions(
                logging_level=logging_level,
                metrics_enabled=default_stage_configuration["metrics_enabled"],
            )

        # Defining Rest API Gateway with Lambda Integration
        self._lambda_rest_api = api_gateway.LambdaRestApi(
            self,
            id=api_gateway_name,
            rest_api_name=api_gateway_name,
            description=api_gateway_name_description,
            domain_name=domain_options,
            handler=self._handler_function,
            proxy=proxy_configuration,
            binary_media_types=binary_media_types,
            default_cors_preflight_options=default_cors_options,
            cloud_watch_role=True,
            deploy_options=default_stage_options,
        )

        # Add Custom responses
        self._lambda_rest_api.add_gateway_response(
            f"{self.prefix}_4XXresponse_{self.environment_}",
            type=api_gateway.ResponseType.DEFAULT_4_XX,
            response_headers={"Access-Control-Allow-Origin": "'*'"},
        )
        self._lambda_rest_api.add_gateway_response(
            f"{self.prefix}_5XXresponse_{self.environment_}",
            type=api_gateway.ResponseType.DEFAULT_5_XX,
            response_headers={"Access-Control-Allow-Origin": "'*'"},
        )

        # Define API Gateway Root Methods
        root_methods = api_configuration["settings"].get(
            "default_http_methods", list())
        for method in root_methods:
            self._lambda_rest_api.root.add_method(
                http_method=method, authorizer=self._gateway_authorizer)

        # Defining Resource Trees for API Gateway with Custom Integrations
        resource_trees = api_configuration["resource_trees"]
        for resource_tree in resource_trees:
            resource_base = self._lambda_rest_api.root.add_resource(
                path_part=resource_tree["resource_name"])
            resource_base_handler = base_lambda_function(
                self, **resource_tree["handler"])
            for method in resource_tree["methods"]:
                resource_base.add_method(
                    http_method=method,
                    integration=api_gateway.LambdaIntegration(
                        handler=resource_base_handler),
                    authorizer=self._gateway_authorizer,
                )
            # resource_base.add_cors_preflight(allow_methods=resource_tree["methods"], allow_origins=["*"])

            resource_base_child_definition = resource_tree.get("child")
            if resource_base_child_definition is not None:
                resource_base_child = resource_base.add_resource(
                    path_part=resource_base_child_definition["resource_name"])
                resource_base_child_handler = base_lambda_function(
                    self, **resource_base_child_definition["handler"])
                for method in resource_base_child_definition["methods"]:
                    resource_base_child.add_method(
                        http_method=method,
                        integration=api_gateway.LambdaIntegration(
                            handler=resource_base_child_handler),
                        authorizer=self._gateway_authorizer,
                    )
                # resource_base_child.add_cors_preflight(
                #     allow_methods=resource_base_child_definition["methods"], allow_origins=["*"]
                # )

                resource_base_child_trees = resource_base_child_definition.get(
                    "childs", list())
                for resource_base_grandchild_tree in resource_base_child_trees:
                    resource_base_grandchild = resource_base_child.add_resource(
                        path_part=resource_base_grandchild_tree[
                            "resource_name"])
                    resource_base_grandchild_handler = base_lambda_function(
                        self, **resource_base_grandchild_tree["handler"])
                    for method in resource_base_grandchild_tree["methods"]:
                        resource_base_grandchild.add_method(
                            http_method=method,
                            integration=api_gateway.LambdaIntegration(
                                handler=resource_base_grandchild_handler),
                            authorizer=self._gateway_authorizer,
                        )