예제 #1
0
 def add_s3_and_dynamodb(self)->None:
   self.gateways = {}
   for svc in ['s3', 'dynamodb']:
     self.gateways[svc] = ec2.GatewayVpcEndpoint(
       self, svc,
       vpc=self.vpc,
       service=ec2.GatewayVpcEndpointAwsService(
         name=svc))
예제 #2
0
 def add_gateways(self)->IVpcEndpointsForAWSServices:
   for svc in ['s3', 'dynamodb']:
     self.gateways[svc] = ec2.GatewayVpcEndpoint(
       self, svc,
       vpc=self.vpc,
       service=ec2.GatewayVpcEndpointAwsService(
         name=svc))
   return self
    def __init__(self, scope: core.Construct, id: str, vpc: ec2.IVpc,
                 **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        self.security_group = ec2.SecurityGroup(
            self,
            'EndpointSecurity',
            vpc=vpc,
            allow_all_outbound=True,
            description='SG for AWS Resources in isolated subnet')

        self.security_group.add_ingress_rule(
            peer=ec2.Peer.any_ipv4(),
            connection=ec2.Port(protocol=ec2.Protocol.ALL,
                                string_representation='Any source'))

        self.gateways = {}
        for svc in ['s3', 'dynamodb']:
            self.gateways[svc] = ec2.GatewayVpcEndpoint(
                self,
                svc,
                vpc=vpc,
                service=ec2.GatewayVpcEndpointAwsService(name=svc))

        self.interfaces = {}
        for svc in [
                'ssm', 'ec2messages', 'ec2', 'ssmmessages', 'kms',
                'elasticloadbalancing', 'elasticfilesystem', 'lambda',
                'states', 'events', 'execute-api', 'kinesis-streams',
                'kinesis-firehose', 'logs', 'sns', 'sqs', 'secretsmanager',
                'config', 'ecr.api', 'ecr.dkr'
        ]:

            self.interfaces[svc] = ec2.InterfaceVpcEndpoint(
                self,
                svc,
                vpc=vpc,
                service=ec2.InterfaceVpcEndpointAwsService(name=svc),
                open=True,
                private_dns_enabled=True,
                lookup_supported_azs=False,
                security_groups=[self.security_group])
예제 #4
0
    def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        isolated_subnets = ec2.SubnetConfiguration(
            name="Isolated",
            subnet_type=ec2.SubnetType.PRIVATE_ISOLATED,
            cidr_mask=24)

        # create VPC
        vpc = ec2.Vpc(self,
                      'AWS-Cookbook-VPC',
                      cidr='10.10.0.0/23',
                      subnet_configuration=[isolated_subnets])

        # -------- Begin EC2 Helper ---------
        vpc.add_interface_endpoint(
            'VPCSSMInterfaceEndpoint',
            service=ec2.InterfaceVpcEndpointAwsService(
                'ssm'
            ),  # Find names with - aws ec2 describe-vpc-endpoint-services | jq '.ServiceNames'
            private_dns_enabled=True,
            subnets=ec2.SubnetSelection(
                one_per_az=False, subnet_type=ec2.SubnetType.PRIVATE_ISOLATED),
        )

        vpc.add_interface_endpoint(
            'VPCEC2MessagesInterfaceEndpoint',
            service=ec2.InterfaceVpcEndpointAwsService(
                'ec2messages'
            ),  # Find names with - aws ec2 describe-vpc-endpoint-services | jq '.ServiceNames'
            private_dns_enabled=True,
            subnets=ec2.SubnetSelection(
                one_per_az=False, subnet_type=ec2.SubnetType.PRIVATE_ISOLATED),
        )

        vpc.add_interface_endpoint(
            'VPCSSMMessagesInterfaceEndpoint',
            service=ec2.InterfaceVpcEndpointAwsService(
                'ssmmessages'
            ),  # Find names with - aws ec2 describe-vpc-endpoint-services | jq '.ServiceNames'
            private_dns_enabled=True,
            subnets=ec2.SubnetSelection(
                one_per_az=False, subnet_type=ec2.SubnetType.PRIVATE_ISOLATED),
        )

        ami = ec2.MachineImage.latest_amazon_linux(
            generation=ec2.AmazonLinuxGeneration.AMAZON_LINUX_2,
            edition=ec2.AmazonLinuxEdition.STANDARD,
            virtualization=ec2.AmazonLinuxVirt.HVM,
            storage=ec2.AmazonLinuxStorage.GENERAL_PURPOSE)

        vpc.add_gateway_endpoint(
            's3GateWayEndPoint',
            service=ec2.GatewayVpcEndpointAwsService('s3'),
            subnets=[
                ec2.SubnetSelection(
                    subnet_type=ec2.SubnetType.PRIVATE_ISOLATED)
            ],
        )

        iam_role = iam.Role(
            self,
            "InstanceSSM",
            assumed_by=iam.ServicePrincipal("ec2.amazonaws.com"))

        iam_role.add_managed_policy(
            iam.ManagedPolicy.from_aws_managed_policy_name(
                "service-role/AmazonEC2RoleforSSM"))

        instance1_sg = ec2.SecurityGroup(self, 'instance1_sg', vpc=vpc)

        instance1 = ec2.Instance(
            self,
            "Instance1",
            instance_type=ec2.InstanceType("t3.nano"),
            machine_image=ami,
            role=iam_role,
            vpc=vpc,
            security_group=instance1_sg,
            vpc_subnets=ec2.SubnetSelection(subnets=[vpc.isolated_subnets[0]]))

        instance2_sg = ec2.SecurityGroup(self, 'instance2_sg', vpc=vpc)

        instance2 = ec2.Instance(
            self,
            "Instance2",
            instance_type=ec2.InstanceType("t3.nano"),
            machine_image=ami,
            role=iam_role,
            vpc=vpc,
            security_group=instance2_sg,
            vpc_subnets=ec2.SubnetSelection(subnets=[vpc.isolated_subnets[1]]))

        # outputs

        CfnOutput(self, 'InstanceId1', value=instance1.instance_id)

        CfnOutput(self, 'InstanceId2', value=instance2.instance_id)

        CfnOutput(self, 'InstanceSgId1', value=instance1_sg.security_group_id)

        CfnOutput(self, 'InstanceSgId2', value=instance2_sg.security_group_id)
    def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        # create s3 bucket
        s3_Bucket = s3.Bucket(self,
                              "AWS-Cookbook-Recipe-402",
                              removal_policy=RemovalPolicy.DESTROY)

        aws_s3_deployment.BucketDeployment(
            self,
            'S3Deployment',
            destination_bucket=s3_Bucket,
            sources=[aws_s3_deployment.Source.asset("./s3_content")],
            retain_on_delete=False)

        isolated_subnets = ec2.SubnetConfiguration(
            name="ISOLATED",
            subnet_type=ec2.SubnetType.PRIVATE_ISOLATED,
            cidr_mask=24)

        # create VPC
        vpc = ec2.Vpc(self,
                      'AWS-Cookbook-VPC',
                      cidr='10.10.0.0/23',
                      subnet_configuration=[isolated_subnets])

        vpc.add_interface_endpoint(
            'VPCSecretsManagerInterfaceEndpoint',
            service=ec2.InterfaceVpcEndpointAwsService(
                'secretsmanager'
            ),  # Find names with - aws ec2 describe-vpc-endpoint-services | jq '.ServiceNames'
            private_dns_enabled=True,
            subnets=ec2.SubnetSelection(
                one_per_az=False, subnet_type=ec2.SubnetType.PRIVATE_ISOLATED),
        )

        vpc.add_interface_endpoint(
            'VPCRDSInterfaceEndpoint',
            service=ec2.InterfaceVpcEndpointAwsService(
                'rds'
            ),  # Find names with - aws ec2 describe-vpc-endpoint-services | jq '.ServiceNames'
            private_dns_enabled=True,
            subnets=ec2.SubnetSelection(
                one_per_az=False, subnet_type=ec2.SubnetType.PRIVATE_ISOLATED),
        )

        vpc.add_gateway_endpoint(
            's3GateWayEndPoint',
            service=ec2.GatewayVpcEndpointAwsService('s3'),
            subnets=[
                ec2.SubnetSelection(
                    subnet_type=ec2.SubnetType.PRIVATE_ISOLATED)
            ],
        )

        rds_security_group = ec2.SecurityGroup(
            self,
            'rds_security_group',
            description='Security Group for the RDS Instance',
            allow_all_outbound=True,
            vpc=vpc)

        rds_instance = rds.DatabaseInstance(
            self,
            'DBInstance',
            engine=rds.DatabaseInstanceEngine.mysql(
                version=rds.MysqlEngineVersion.VER_8_0_23),
            instance_type=ec2.InstanceType("m5.large"),
            vpc=vpc,
            database_name='AWSCookbookRecipe402',
            instance_identifier='awscookbookrecipe402',
            delete_automated_backups=True,
            deletion_protection=False,
            removal_policy=RemovalPolicy.DESTROY,
            allocated_storage=8,
            vpc_subnets=ec2.SubnetSelection(
                one_per_az=False, subnet_type=ec2.SubnetType.PRIVATE_ISOLATED),
            security_groups=[rds_security_group])

        # -------- Begin EC2 Helper ---------
        vpc.add_interface_endpoint(
            'VPCSSMInterfaceEndpoint',
            service=ec2.InterfaceVpcEndpointAwsService(
                'ssm'
            ),  # Find names with - aws ec2 describe-vpc-endpoint-services | jq '.ServiceNames'
            private_dns_enabled=True,
            subnets=ec2.SubnetSelection(
                one_per_az=False, subnet_type=ec2.SubnetType.PRIVATE_ISOLATED),
        )

        vpc.add_interface_endpoint(
            'VPCEC2MessagesInterfaceEndpoint',
            service=ec2.InterfaceVpcEndpointAwsService(
                'ec2messages'
            ),  # Find names with - aws ec2 describe-vpc-endpoint-services | jq '.ServiceNames'
            private_dns_enabled=True,
            subnets=ec2.SubnetSelection(
                one_per_az=False, subnet_type=ec2.SubnetType.PRIVATE_ISOLATED),
        )

        vpc.add_interface_endpoint(
            'VPCSSMMessagesInterfaceEndpoint',
            service=ec2.InterfaceVpcEndpointAwsService(
                'ssmmessages'
            ),  # Find names with - aws ec2 describe-vpc-endpoint-services | jq '.ServiceNames'
            private_dns_enabled=True,
            subnets=ec2.SubnetSelection(
                one_per_az=False, subnet_type=ec2.SubnetType.PRIVATE_ISOLATED),
        )

        ami = ec2.MachineImage.latest_amazon_linux(
            generation=ec2.AmazonLinuxGeneration.AMAZON_LINUX_2,
            edition=ec2.AmazonLinuxEdition.STANDARD,
            virtualization=ec2.AmazonLinuxVirt.HVM,
            storage=ec2.AmazonLinuxStorage.GENERAL_PURPOSE)

        iam_role = iam.Role(
            self,
            "InstanceSSM",
            assumed_by=iam.ServicePrincipal("ec2.amazonaws.com"))

        iam_role.add_managed_policy(
            iam.ManagedPolicy.from_aws_managed_policy_name(
                "service-role/AmazonEC2RoleforSSM"))

        instance = ec2.Instance(
            self,
            "Instance",
            instance_type=ec2.InstanceType("t3.nano"),
            machine_image=ami,
            role=iam_role,
            vpc=vpc,
        )

        CfnOutput(self, 'InstanceId', value=instance.instance_id)
        # -------- End EC2 Helper ---------

        rds_instance.secret.grant_read(instance)

        # allow connection from ec2 instance to DB
        rds_instance.connections.allow_from(instance.connections,
                                            ec2.Port.tcp(3306), "Ingress")

        s3_Bucket.grant_read(instance)

        # outputs

        CfnOutput(self, 'VpcId', value=vpc.vpc_id)

        CfnOutput(self,
                  'RdsSecurityGroup',
                  value=rds_security_group.security_group_id)

        CfnOutput(self,
                  'RdsDatabaseId',
                  value=rds_instance.instance_identifier)

        CfnOutput(self,
                  'RdsEndpoint',
                  value=rds_instance.db_instance_endpoint_address)

        CfnOutput(self,
                  'RdsPort',
                  value=rds_instance.db_instance_endpoint_port)

        CfnOutput(self, 'BucketName', value=s3_Bucket.bucket_name)

        isolated_subnets = vpc.select_subnets(
            subnet_type=ec2.SubnetType.PRIVATE_ISOLATED)

        CfnOutput(self,
                  'IsolatedSubnets',
                  value=', '.join(map(str, isolated_subnets.subnet_ids)))

        CfnOutput(self, 'InstanceRoleName', value=iam_role.role_name)

        CfnOutput(self,
                  'RdsSecretArn',
                  value=rds_instance.secret.secret_full_arn)
    def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        # create s3 bucket
        s3_Bucket = s3.Bucket(self,
                              "AWS-Cookbook-Recipe-404",
                              removal_policy=RemovalPolicy.DESTROY,
                              auto_delete_objects=True)

        aws_s3_deployment.BucketDeployment(
            self,
            'S3Deployment',
            destination_bucket=s3_Bucket,
            sources=[aws_s3_deployment.Source.asset("./s3_content")],
            retain_on_delete=False)

        isolated_subnets = ec2.SubnetConfiguration(
            name="ISOLATED",
            subnet_type=ec2.SubnetType.PRIVATE_ISOLATED,
            cidr_mask=24)

        # create VPC
        vpc = ec2.Vpc(self,
                      'AWS-Cookbook-VPC',
                      cidr='10.10.0.0/23',
                      subnet_configuration=[isolated_subnets])

        vpc.add_interface_endpoint(
            'VPCSecretsManagerInterfaceEndpoint',
            service=ec2.InterfaceVpcEndpointAwsService(
                'secretsmanager'
            ),  # Find names with - aws ec2 describe-vpc-endpoint-services | jq '.ServiceNames'
            private_dns_enabled=True,
            subnets=ec2.SubnetSelection(
                one_per_az=False, subnet_type=ec2.SubnetType.PRIVATE_ISOLATED),
        )

        vpc.add_gateway_endpoint(
            's3GateWayEndPoint',
            service=ec2.GatewayVpcEndpointAwsService('s3'),
            subnets=[
                ec2.SubnetSelection(
                    subnet_type=ec2.SubnetType.PRIVATE_ISOLATED)
            ],
        )

        subnet_group = rds.SubnetGroup(
            self,
            'rds_subnet_group',
            description='VPC Subnet Group for RDS',
            vpc=vpc,
            vpc_subnets=ec2.SubnetSelection(
                one_per_az=False, subnet_type=ec2.SubnetType.PRIVATE_ISOLATED))

        rds_instance = rds.DatabaseInstance(
            self,
            'DBInstance',
            engine=rds.DatabaseInstanceEngine.mysql(
                version=rds.MysqlEngineVersion.VER_8_0_23),
            instance_type=ec2.InstanceType("m5.large"),
            vpc=vpc,
            multi_az=False,
            database_name='AWSCookbookRecipe404',
            instance_identifier='awscookbook404db-orig',
            delete_automated_backups=True,
            deletion_protection=False,
            # iam_authentication=
            removal_policy=RemovalPolicy.DESTROY,
            allocated_storage=8,
            subnet_group=subnet_group)

        # mkdir -p lambda-layers/sqlparse/python
        # cd layers/sqlparse/python
        # pip install sqlparse --target="."
        # cd ../../../

        # create Lambda Layer
        sqlparse = aws_lambda.LayerVersion(
            self,
            "sqlparse",
            code=aws_lambda.AssetCode('lambda-layers/sqlparse'),
            compatible_runtimes=[aws_lambda.Runtime.PYTHON_3_8],
            description="sqlparse",
            license=
            "https://github.com/andialbrecht/sqlparse/blob/master/LICENSE")

        pymysql = aws_lambda.LayerVersion(
            self,
            "pymysql",
            code=aws_lambda.AssetCode('lambda-layers/pymysql'),
            compatible_runtimes=[aws_lambda.Runtime.PYTHON_3_8],
            description="pymysql",
            license="MIT")

        smartopen = aws_lambda.LayerVersion(
            self,
            "smartopen",
            code=aws_lambda.AssetCode('lambda-layers/smart_open'),
            compatible_runtimes=[aws_lambda.Runtime.PYTHON_3_8],
            description="smartopen",
            license="MIT")

        lambda_function = aws_lambda.Function(
            self,
            'LambdaRDS',
            code=aws_lambda.AssetCode("./mysql-lambda/"),
            handler="lambda_function.lambda_handler",
            environment={
                "DB_SECRET_ARN": rds_instance.secret.secret_arn,
                "S3_BUCKET": s3_Bucket.bucket_name
            },
            layers=[sqlparse, pymysql, smartopen],
            memory_size=1024,
            runtime=aws_lambda.Runtime.PYTHON_3_8,
            timeout=Duration.seconds(600),
            vpc=vpc,
            vpc_subnets=ec2.SubnetSelection(
                subnet_type=ec2.SubnetType.PRIVATE_ISOLATED))

        rds_instance.secret.grant_read(lambda_function)

        rds_instance.connections.allow_from(lambda_function.connections,
                                            ec2.Port.tcp(3306), "Ingress")

        s3_Bucket.grant_read(lambda_function)

        create_params = {
            "FunctionName": lambda_function.function_arn,
        }

        on_create = custom_resources.AwsSdkCall(
            action='invoke',
            service='Lambda',
            parameters=create_params,
            physical_resource_id=custom_resources.PhysicalResourceId.of(
                'LambdaRDS'))

        policy_statement = iam.PolicyStatement(
            actions=["lambda:InvokeFunction"],
            effect=iam.Effect.ALLOW,
            resources=[lambda_function.function_arn],
        )

        policy = custom_resources.AwsCustomResourcePolicy.from_statements(
            statements=[policy_statement])

        custom_resources.AwsCustomResource(
            self,
            'CustomResource',
            policy=policy,
            on_create=on_create,
            log_retention=logs.RetentionDays.TWO_WEEKS)

        # outputs

        CfnOutput(self, 'RdsSubnetGroup', value=subnet_group.subnet_group_name)

        CfnOutput(self,
                  'RdsDatabaseId',
                  value=rds_instance.instance_identifier)
예제 #7
0
 def add_gateway_endpoint(self, endpoint: str):
     self.vpc.add_gateway_endpoint(
         endpoint + "_endpoint",
         service=ec2.GatewayVpcEndpointAwsService(endpoint))
예제 #8
0
    def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        # create s3 bucket
        s3_Bucket = s3.Bucket(self,
                              "AWS-Cookbook-Recipe-407",
                              removal_policy=RemovalPolicy.DESTROY)

        aws_s3_deployment.BucketDeployment(
            self,
            'S3Deployment',
            destination_bucket=s3_Bucket,
            sources=[aws_s3_deployment.Source.asset("./s3_content")],
            retain_on_delete=False)

        isolated_subnets = ec2.SubnetConfiguration(
            name="ISOLATED",
            subnet_type=ec2.SubnetType.PRIVATE_ISOLATED,
            cidr_mask=24)

        # create VPC
        vpc = ec2.Vpc(self,
                      'AWS-Cookbook-VPC',
                      cidr='10.10.0.0/23',
                      subnet_configuration=[isolated_subnets])

        vpc.add_interface_endpoint(
            'VPCSSMInterfaceEndpoint',
            service=ec2.InterfaceVpcEndpointAwsService(
                'ssm'
            ),  # Find names with - aws ec2 describe-vpc-endpoint-services | jq '.ServiceNames'
            private_dns_enabled=True,
            subnets=ec2.SubnetSelection(
                one_per_az=False, subnet_type=ec2.SubnetType.PRIVATE_ISOLATED),
        )

        vpc.add_interface_endpoint(
            'VPCEC2MessagesInterfaceEndpoint',
            service=ec2.InterfaceVpcEndpointAwsService(
                'ec2messages'
            ),  # Find names with - aws ec2 describe-vpc-endpoint-services | jq '.ServiceNames'
            private_dns_enabled=True,
            subnets=ec2.SubnetSelection(
                one_per_az=False, subnet_type=ec2.SubnetType.PRIVATE_ISOLATED),
        )

        vpc.add_interface_endpoint(
            'VPCSSMMessagedInterfaceEndpoint',
            service=ec2.InterfaceVpcEndpointAwsService(
                'ssmmessages'
            ),  # Find names with - aws ec2 describe-vpc-endpoint-services | jq '.ServiceNames'
            private_dns_enabled=True,
            subnets=ec2.SubnetSelection(
                one_per_az=False, subnet_type=ec2.SubnetType.PRIVATE_ISOLATED),
        )

        vpc.add_interface_endpoint(
            'VPCSecretsManagerInterfaceEndpoint',
            service=ec2.InterfaceVpcEndpointAwsService(
                'secretsmanager'
            ),  # Find names with - aws ec2 describe-vpc-endpoint-services | jq '.ServiceNames'
            private_dns_enabled=True,
            subnets=ec2.SubnetSelection(
                one_per_az=False, subnet_type=ec2.SubnetType.PRIVATE_ISOLATED),
        )

        vpc.add_gateway_endpoint(
            's3GateWayEndPoint',
            service=ec2.GatewayVpcEndpointAwsService('s3'),
            subnets=[
                ec2.SubnetSelection(
                    subnet_type=ec2.SubnetType.PRIVATE_ISOLATED)
            ],
        )

        ami = ec2.MachineImage.latest_amazon_linux(
            generation=ec2.AmazonLinuxGeneration.AMAZON_LINUX_2,
            edition=ec2.AmazonLinuxEdition.STANDARD,
            virtualization=ec2.AmazonLinuxVirt.HVM,
            storage=ec2.AmazonLinuxStorage.GENERAL_PURPOSE)

        iam_role = iam.Role(
            self,
            "InstanceSSM",
            assumed_by=iam.ServicePrincipal("ec2.amazonaws.com"))

        iam_role.add_managed_policy(
            iam.ManagedPolicy.from_aws_managed_policy_name(
                "service-role/AmazonEC2RoleforSSM"))

        instance = ec2.Instance(
            self,
            "Instance",
            instance_type=ec2.InstanceType("t3.nano"),
            machine_image=ami,
            role=iam_role,
            vpc=vpc,
        )

        subnet_group = rds.SubnetGroup(
            self,
            'rds_subnet_group',
            description='VPC Subnet Group for RDS',
            vpc=vpc,
            vpc_subnets=ec2.SubnetSelection(
                one_per_az=False, subnet_type=ec2.SubnetType.PRIVATE_ISOLATED))

        source_rds_security_group = ec2.SecurityGroup(
            self,
            'source_rds_security_group',
            description='Security Group for the Source RDS Instance',
            allow_all_outbound=True,
            vpc=vpc)

        source_db_name = 'AWSCookbookRecipe407Source'

        source_rds_instance = rds.DatabaseInstance(
            self,
            'source_rds_instance',
            engine=rds.DatabaseInstanceEngine.mysql(
                version=rds.MysqlEngineVersion.VER_5_7_33),
            instance_type=ec2.InstanceType("m5.large"),
            vpc=vpc,
            multi_az=False,
            database_name=source_db_name,
            instance_identifier='awscookbook407SourceDb',
            delete_automated_backups=True,
            deletion_protection=False,
            # iam_authentication=
            removal_policy=RemovalPolicy.DESTROY,
            allocated_storage=8,
            subnet_group=subnet_group,
            security_groups=[source_rds_security_group])

        source_rds_instance.connections.allow_from(instance.connections,
                                                   ec2.Port.tcp(3306),
                                                   "Ingress")

        target_rds_security_group = ec2.SecurityGroup(
            self,
            'target_rds_security_group',
            description='Security Group for the Target RDS Instance',
            allow_all_outbound=True,
            vpc=vpc)

        target_db_name = 'AWSCookbookRecipe407Target'

        target_rds_instance = rds.DatabaseInstance(
            self,
            'target_rds_instance',
            engine=rds.DatabaseInstanceEngine.mysql(
                version=rds.MysqlEngineVersion.VER_5_7_26),
            instance_type=ec2.InstanceType("m5.large"),
            vpc=vpc,
            multi_az=False,
            database_name=target_db_name,
            instance_identifier='awscookbook407TargetDb',
            delete_automated_backups=True,
            deletion_protection=False,
            # iam_authentication=
            removal_policy=RemovalPolicy.DESTROY,
            allocated_storage=8,
            subnet_group=subnet_group,
            security_groups=[target_rds_security_group])

        target_rds_instance.connections.allow_from(instance.connections,
                                                   ec2.Port.tcp(3306),
                                                   "Ingress")

        # mkdir -p lambda-layers/sqlparse/python
        # cd layers/sqlparse/python
        # pip install sqlparse --target="."
        # cd ../../../

        # create Lambda Layer
        sqlparse = aws_lambda.LayerVersion(
            self,
            "sqlparse",
            code=aws_lambda.AssetCode('lambda-layers/sqlparse'),
            compatible_runtimes=[aws_lambda.Runtime.PYTHON_3_8],
            description="sqlparse",
            license=
            "https://github.com/andialbrecht/sqlparse/blob/master/LICENSE")

        pymysql = aws_lambda.LayerVersion(
            self,
            "pymysql",
            code=aws_lambda.AssetCode('lambda-layers/pymysql'),
            compatible_runtimes=[aws_lambda.Runtime.PYTHON_3_8],
            description="pymysql",
            license="MIT")

        smartopen = aws_lambda.LayerVersion(
            self,
            "smartopen",
            code=aws_lambda.AssetCode('lambda-layers/smart_open'),
            compatible_runtimes=[aws_lambda.Runtime.PYTHON_3_8],
            description="smartopen",
            license="MIT")

        lambda_function = aws_lambda.Function(
            self,
            'LambdaRDS',
            code=aws_lambda.AssetCode("./mysql-lambda/"),
            handler="lambda_function.lambda_handler",
            environment={
                "DB_SECRET_ARN": source_rds_instance.secret.secret_arn,
                "S3_BUCKET": s3_Bucket.bucket_name
            },
            layers=[sqlparse, pymysql, smartopen],
            memory_size=1024,
            runtime=aws_lambda.Runtime.PYTHON_3_8,
            timeout=Duration.seconds(600),
            vpc=vpc,
            vpc_subnets=ec2.SubnetSelection(
                subnet_type=ec2.SubnetType.PRIVATE_ISOLATED))

        source_rds_instance.secret.grant_read(lambda_function)

        source_rds_instance.connections.allow_from(lambda_function.connections,
                                                   ec2.Port.tcp(3306),
                                                   "Ingress")

        s3_Bucket.grant_read(lambda_function)

        # outputs

        CfnOutput(self, 'VpcId', value=vpc.vpc_id)

        CfnOutput(self, 'InstanceId', value=instance.instance_id)

        CfnOutput(self,
                  'SourceRdsDatabaseId',
                  value=source_rds_instance.instance_identifier)

        CfnOutput(self,
                  'SourceRdsSecurityGroup',
                  value=source_rds_security_group.security_group_id)

        CfnOutput(self, 'SourceDbName', value=source_db_name)

        CfnOutput(self,
                  'SourceRdsSecretArn',
                  value=source_rds_instance.secret.secret_full_arn)

        CfnOutput(self,
                  'SourceRdsEndpoint',
                  value=source_rds_instance.db_instance_endpoint_address)

        CfnOutput(self,
                  'TargetRdsDatabaseId',
                  value=target_rds_instance.instance_identifier)

        CfnOutput(self,
                  'TargetRdsSecurityGroup',
                  value=target_rds_security_group.security_group_id)

        CfnOutput(self, 'TargetDbName', value=target_db_name)

        CfnOutput(self,
                  'TargetRdsSecretArn',
                  value=target_rds_instance.secret.secret_full_arn)

        CfnOutput(self,
                  'TargetRdsEndpoint',
                  value=target_rds_instance.db_instance_endpoint_address)

        isolated_subnets = vpc.select_subnets(
            subnet_type=ec2.SubnetType.PRIVATE_ISOLATED)

        CfnOutput(self,
                  'IsolatedSubnets',
                  value=', '.join(map(str, isolated_subnets.subnet_ids)))

        CfnOutput(self, 'LambdaArn', value=lambda_function.function_arn)

        CfnOutput(self,
                  'RdsSourceSecretName',
                  value=source_rds_instance.secret.secret_name)

        CfnOutput(self,
                  'RdsTargetSecretName',
                  value=target_rds_instance.secret.secret_name)