Esempio n. 1
0
    def __init__(self, scope: core.Construct, id: str, vpc: aws_ec2.Vpc,
                 **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        _subnets = []
        _subnets.append(
            aws_ec2.Subnet(self,
                           'sbn-redshift-1',
                           availability_zone=vpc.availability_zones[0],
                           vpc_id=vpc.vpc_id,
                           cidr_block='10.0.4.0/25'))

        _subnets.append(
            aws_ec2.Subnet(self,
                           'sbn-redshift-2',
                           availability_zone=vpc.availability_zones[1],
                           vpc_id=vpc.vpc_id,
                           cidr_block='10.0.4.128/25'))

        _cluster_subnet_group = aws_redshift.ClusterSubnetGroup(
            self,
            'deta-pipeline-redshift-subnet',
            description='redshift cluster subnet',
            vpc=vpc,
            vpc_subnets=aws_ec2.SubnetSelection(subnets=_subnets))

        aws_redshift.Cluster(
            self,
            'destination-redshift',
            master_user=aws_redshift.Login(master_username='******'),
            vpc=vpc,
            subnet_group=_cluster_subnet_group)
    def __init__(self, scope: core.Construct, id: str, vpc: VpcStack,
                 **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        subnet_group = redshift.ClusterSubnetGroup(
            self,
            id="RedshiftSubnetGroup",
            description="Redshift private subnet group",
            vpc=vpc.instance,
            vpc_subnets=ec2.SubnetSelection(
                subnet_type=ec2.SubnetType.ISOLATED),
        )

        self.redshift_secret = sm.Secret(
            self,
            "redshift-credentials",
            secret_name="redshift-credentials",
            description="Credentials for Amazon Redshift cluster.",
            generate_secret_string=sm.SecretStringGenerator(
                secret_string_template='{"username": "******"}',
                generate_string_key="password",
                password_length=32,
                exclude_characters='"@\\\/',
                exclude_punctuation=True,
            ),
        )

        redshift_login = redshift.Login(
            master_username="******",
            master_password=self.redshift_secret.secret_value_from_json(
                "password"),
        )

        redshift_s3_read_access_role = iam.Role(
            self,
            "redshiftS3AccessRole",
            role_name="redshiftS3AccessRole",
            assumed_by=iam.ServicePrincipal("redshift.amazonaws.com"),
            managed_policies=[
                iam.ManagedPolicy.from_aws_managed_policy_name(
                    "AmazonS3ReadOnlyAccess")
            ],
        )

        redshift_cluster = redshift.Cluster(
            self,
            id="redshift-cluster",
            master_user=redshift_login,
            vpc=vpc,
            cluster_type=redshift.ClusterType.SINGLE_NODE,
            default_database_name="redshift-db",
            encrypted=True,
            node_type=redshift.NodeType.DC2_LARGE,
            port=5439,
            roles=[redshift_s3_read_access_role],
            security_groups=[vpc.redshift_sg],
            subnet_group=subnet_group,
            removal_policy=core.RemovalPolicy.DESTROY,
        )
        self._instance = redshift_cluster
Esempio n. 3
0
    def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        nat_instance = aws_ec2.NatProvider.instance(
            instance_type=aws_ec2.InstanceType('t3a.nano'))

        vpc = aws_ec2.Vpc(self,
                          'VPC',
                          max_azs=1,
                          nat_gateway_provider=nat_instance)

        cluster_security_group = aws_ec2.SecurityGroup(
            self,
            'ClusterSecurityGroup',
            vpc=vpc,
            allow_all_outbound=True,
            description="Allow Glue Job to access redshift",
            security_group_name="serverless-redshift-query-testing-redshift")

        cluster = aws_redshift.Cluster(
            self,
            'Cluster',
            cluster_name='serverless-redshift-query-testing',
            master_user=aws_redshift.Login(master_username='******'),
            vpc=vpc,
            removal_policy=core.RemovalPolicy.DESTROY,
            security_groups=[cluster_security_group])

        app = aws_sam.CfnApplication(
            self,
            'RedshiftQueryGlueJob',
            location=
            'https://redshift-query.s3-eu-west-1.amazonaws.com/glue-job-template.yaml',
            parameters={
                'ClusterId': 'serverless-redshift-query-testing',
                'SQLStatements': "select 1;",
                'Loglevel': "ERROR"
            })

        glue_job_security_group_ref = app.get_att(
            'Outputs.SecurityGroup').to_string()
        glue_job_security_group = aws_ec2.SecurityGroup.from_security_group_id(
            self, 'GlueSecurityGroup', glue_job_security_group_ref)

        cluster_security_group.add_ingress_rule(
            peer=glue_job_security_group,
            connection=aws_ec2.Port(protocol=aws_ec2.Protocol.TCP,
                                    from_port=5439,
                                    to_port=5439,
                                    string_representation='Redshift Port'))

        app.node.add_dependency(cluster)
Esempio n. 4
0
    def __init__(
        self,
        scope: core.Construct,
        common_stack: CommonResourcesStack,
        data_lake_silver_bucket: BaseDataLakeBucket,
        data_lake_gold_bucket: BaseDataLakeBucket,
        **kwargs,
    ) -> None:
        self.common_stack = common_stack
        self.deploy_env = active_environment
        self.data_lake_silver_bucket = data_lake_silver_bucket
        self.data_lake_gold_bucket = data_lake_gold_bucket
        super().__init__(scope,
                         id=f"{self.deploy_env.value}-redshift-stack",
                         **kwargs)

        self.redshift_sg = ec2.SecurityGroup(
            self,
            f"redshift-{self.deploy_env.value}-sg",
            vpc=self.common_stack.custom_vpc,
            allow_all_outbound=True,
            security_group_name=f"redshift-{self.deploy_env.value}-sg",
        )

        self.redshift_sg.add_ingress_rule(peer=ec2.Peer.ipv4("0.0.0.0/0"),
                                          connection=ec2.Port.tcp(5439))

        for subnet in self.common_stack.custom_vpc.private_subnets:
            self.redshift_sg.add_ingress_rule(
                peer=ec2.Peer.ipv4(subnet.ipv4_cidr_block),
                connection=ec2.Port.tcp(5439),
            )

        self.redshift_cluster = redshift.Cluster(
            self,
            f"ecommerce-{self.deploy_env.value}-redshift",
            cluster_name=f"ecommerce-{self.deploy_env.value}-redshift",
            vpc=self.common_stack.custom_vpc,
            cluster_type=redshift.ClusterType.SINGLE_NODE,
            node_type=redshift.NodeType.DC2_LARGE,
            default_database_name="dw",
            number_of_nodes=1,
            removal_policy=core.RemovalPolicy.DESTROY,
            master_user=redshift.Login(master_username="******"),
            publicly_accessible=True,
            roles=[
                SpectrumRole(self, self.data_lake_silver_bucket,
                             self.data_lake_gold_bucket)
            ],
            security_groups=[self.redshift_sg],
            vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
        )
    def __init__(self, scope: core.Construct, id: str, vpc: ec2.Vpc,
                 **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        kms_policy = iam.PolicyDocument()
        kms_policy.add_statements(
            iam.PolicyStatement(
                effect=iam.Effect.ALLOW,
                actions=["kms:*"],
                resources=['*'],
                principals=[iam.AccountPrincipal(account_id=self.account)]))

        redshift_key = kms.Key(self,
                               "volumeKey",
                               enable_key_rotation=True,
                               policy=kms_policy,
                               removal_policy=core.RemovalPolicy.RETAIN)

        redshift_bucket = s3.Bucket(self, "redshiftBucket")
        redshift_bucket.add_to_resource_policy(permission=iam.PolicyStatement(
            effect=iam.Effect.ALLOW,
            actions=["s3:*"],
            resources=[
                f"{redshift_bucket.bucket_arn}/*", redshift_bucket.bucket_arn
            ],
            principals=[
                iam.ArnPrincipal(f"arn:aws:iam::193672423079:user/logs")
            ]))

        self._cluster = redshift.Cluster(
            self,
            id,
            master_user=redshift.Login(master_username="******",
                                       encryption_key=redshift_key),
            port=5439,
            vpc=vpc,
            cluster_name="dwh",
            cluster_type=redshift.ClusterType.MULTI_NODE,
            number_of_nodes=2,
            default_database_name="aml",
            encrypted=True,
            encryption_key=redshift_key,
            logging_bucket=redshift_bucket,
            logging_key_prefix="dwh",
            node_type=redshift.NodeType.DC2_LARGE,
            removal_policy=core.RemovalPolicy.DESTROY,
            security_groups=[self.redshift_sg(vpc)],
            vpc_subnets=ec2.SubnetSelection(subnet_group_name="DBS"))
    def __init__(self, scope: core.Construct, common: Common,
                 data_lake: DataLake, **kwargs) -> None:
        self.env = common.env
        super().__init__(scope, id=f'{self.env}-data-warehouse', **kwargs)

        self.redshift_sg = ec2.SecurityGroup(
            self,
            f'redshift-{self.env}-sg',
            vpc=common.custom_vpc,
            allow_all_outbound=True,
            security_group_name=f'redshift-{self.env}-sg',
        )

        self.redshift_sg.add_ingress_rule(
            peer=ec2.Peer.ipv4('37.156.75.55/32'),
            connection=ec2.Port.tcp(5439))

        for subnet in common.custom_vpc.private_subnets:
            self.redshift_sg.add_ingress_rule(peer=ec2.Peer.ipv4(
                subnet.ipv4_cidr_block),
                                              connection=ec2.Port.tcp(5439))

        self.redshift_cluster = redshift.Cluster(
            self,
            f'belisco-{self.env}-redshift',
            cluster_name=f'belisco-{self.env}-redshift',
            vpc=common.custom_vpc,
            cluster_type=redshift.ClusterType.MULTI_NODE,
            node_type=redshift.NodeType.DC2_LARGE,
            default_database_name='dw',
            number_of_nodes=2,
            removal_policy=core.RemovalPolicy.DESTROY,
            master_user=redshift.Login(master_username='******'),
            publicly_accessible=True,
            roles=[SpectrumRole(self, data_lake)],
            security_groups=[self.redshift_sg],
            vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC))
    def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)
        self.current_dir = os.path.dirname(__file__)

        self.vpc = ec2.Vpc(
            self,
            "VPC",
            cidr="10.0.0.0/21",
            max_azs=2,
            subnet_configuration=[
                ec2.SubnetConfiguration(
                    cidr_mask=28,
                    name="Database",
                    subnet_type=ec2.SubnetType.ISOLATED,
                ),
                ec2.SubnetConfiguration(cidr_mask=28,
                                        name="Private",
                                        subnet_type=ec2.SubnetType.PRIVATE),
                ec2.SubnetConfiguration(cidr_mask=28,
                                        name="Public",
                                        subnet_type=ec2.SubnetType.PUBLIC)
            ],
            nat_gateways=3)

        self.qs_security_group = ec2.SecurityGroup(
            self,
            "quicksight-sg",
            vpc=self.vpc,
            allow_all_outbound=True,
            description="QuickSight security group")

        self.bastion = ec2.BastionHostLinux(
            self,
            "BastionHost",
            vpc=self.vpc,
            subnet_selection=ec2.SubnetSelection(
                subnet_type=ec2.SubnetType.PUBLIC))

        self.bastion.connections.allow_from_any_ipv4(ec2.Port.tcp(22),
                                                     "Internet access SSH")

        self.vpc.add_interface_endpoint(
            "redshift_endpoint",
            service=ec2.InterfaceVpcEndpointAwsService("redshift"))

        self.vpc.add_interface_endpoint(
            "rds_endpoint", service=ec2.InterfaceVpcEndpointAwsService("rds"))

        self.redshift_secret = secrets.Secret(
            self,
            'redshift-admin',
            secret_name='redshift-admin',
            description=
            "This secret has generated admin secret password for Redshift cluster",
            generate_secret_string=secrets.SecretStringGenerator(
                secret_string_template='{"username": "******"}',
                generate_string_key='password',
                password_length=32,
                exclude_characters='"@\\\/',
                exclude_punctuation=True))

        self.rs_security_group = ec2.SecurityGroup(self,
                                                   "redshift-sg",
                                                   vpc=self.vpc,
                                                   allow_all_outbound=True,
                                                   description="Redshift SG")

        self.rs_security_group.add_ingress_rule(self.rs_security_group,
                                                ec2.Port.all_tcp(),
                                                'Redshift-basic')

        self.rs_security_group.add_ingress_rule(
            # https://docs.aws.amazon.com/quicksight/latest/user/regions.html
            ec2.Peer.ipv4('52.23.63.224/27'),
            ec2.Port.tcp(5439),
            'QuickSight-IP')

        self.rs_security_group.add_ingress_rule(self.qs_security_group,
                                                ec2.Port.tcp(5439),
                                                'QuickSight-sg')

        # self.rs_security_group.add_egress_rule(
        #     self.rs_security_group,
        #     ec2.Port.all_tcp(),
        #     'Allow outbound for QuickSight'
        # )

        self.redshift_cluster = redshift.Cluster(
            self,
            "datasource-redshift",
            master_user=redshift.Login(
                master_username="******",
                master_password=self.redshift_secret.secret_value_from_json(
                    'password')),
            vpc=self.vpc,
            vpc_subnets=ec2.SubnetSelection(
                subnet_type=ec2.SubnetType.ISOLATED),
            security_groups=[self.rs_security_group])

        self.rds_secret = secrets.Secret(
            self,
            'rds-admin',
            secret_name='rds-admin',
            description=
            "This secret has generated admin secret password for RDS cluster",
            generate_secret_string=secrets.SecretStringGenerator(
                secret_string_template='{"username": "******"}',
                generate_string_key='password',
                password_length=32,
                exclude_characters='"@\\\/',
                exclude_punctuation=True))

        self.rds_cluster = rds.DatabaseCluster(
            self,
            "datasource-rds",
            engine=rds.DatabaseClusterEngine.aurora_postgres(
                version=rds.AuroraPostgresEngineVersion.VER_11_9),
            instance_props={
                "vpc_subnets": {
                    "subnet_type": ec2.SubnetType.ISOLATED
                },
                "vpc": self.vpc
            },
            credentials=rds.Credentials.from_secret(self.rds_secret))

        self.rds_cluster.connections.allow_default_port_from(
            self.bastion, "EC2 Bastion access Aurora")

        self.rds_cluster.connections.allow_default_port_from(
            self.qs_security_group, "QuickSight-sg")

        self.rds_cluster.connections.allow_default_port_from(
            # https://docs.aws.amazon.com/quicksight/latest/user/regions.html
            ec2.Peer.ipv4('52.23.63.224/27'),
            "QuickSight-IP")

        self.qs_security_group.add_ingress_rule(self.rs_security_group,
                                                ec2.Port.all_tcp(), 'AllTCP')

        for rds_group in self.rds_cluster.connections.security_groups:
            self.qs_security_group.add_ingress_rule(rds_group,
                                                    ec2.Port.all_tcp(),
                                                    'AllTCP')

        # self.qs_security_group.add_egress_rule(
        #     self.rs_security_group,
        #     ec2.Port.all_tcp(),
        #     'AllTCP'
        # )

        core.CfnOutput(self, "vpcId", value=self.vpc.vpc_id)
        core.CfnOutput(self, "redshiftUsername", value="admin")
        core.CfnOutput(self, "redshiftPassword", value="redshift-admin")
        core.CfnOutput(self,
                       "redshiftClusterId",
                       value=self.redshift_cluster.cluster_name)
        core.CfnOutput(self,
                       "redshiftHost",
                       value=self.redshift_cluster.cluster_endpoint.hostname)
        core.CfnOutput(self, "redshiftDB", value="dev")
        core.CfnOutput(self, "rdsUsername", value="administrator")
        core.CfnOutput(self, "rdsPassword", value="rds-admin")
        core.CfnOutput(self,
                       "rdsClusterId",
                       value=self.rds_cluster.cluster_identifier)
        core.CfnOutput(self, "namespace", value="default")
        core.CfnOutput(self, "version", value="1")
        core.CfnOutput(self,
                       "quicksightSecurityGroupId",
                       value=self.qs_security_group.security_group_id)
Esempio n. 8
0
    def __init__(self, scope: core.Construct, id: str, vpc, bastion_sg,
                 glue_sg, clean_bucket: s3.Bucket, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        self.__vpc = vpc
        self.__clean_bucket = clean_bucket

        self.__glue_sg = glue_sg

        self.__redshift_sg = ec2.SecurityGroup(
            self,
            id="redshift-sg",
            vpc=self.__vpc,
            allow_all_outbound=None,
            description=None,
            security_group_name="redshift-sg")

        self.__lambda_sg = ec2.SecurityGroup(
            self,
            id="redshift-lambda-sg",
            vpc=vpc,
            allow_all_outbound=None,
            description=None,
            security_group_name="redshift-lambda-sg")

        self.__redshift_sg.add_ingress_rule(bastion_sg, ec2.Port.tcp(5439))

        self.__redshift_sg.add_ingress_rule(self.__lambda_sg,
                                            ec2.Port.tcp(5439))

        self.__redshift_sg.add_ingress_rule(self.__glue_sg, ec2.Port.tcp(5439))

        self.__security_groups_list = [self.__redshift_sg]

        self.__master_user = {'master_username': "******"}

        self.__subnets_selection = ec2.SubnetSelection(
            availability_zones=None,
            one_per_az=None,
            subnet_group_name=None,
            subnet_name=None,
            subnets=None,
            subnet_type=ec2.SubnetType.PRIVATE)

        # Create role that is used by the Redshift to read data from clean bucket
        self.__s3role = iam.Role(
            self,
            "RedshiftClean",
            assumed_by=iam.ServicePrincipal("redshift.amazonaws.com"))

        self.__s3role.add_to_principal_policy(
            iam.PolicyStatement(actions=[
                's3:GetObject', 's3:ListBucket', 's3:GetBucketLocation',
                's3:ListMultipartUploadParts', 's3:ListBucketMultipartUploads'
            ],
                                resources=[
                                    self.__clean_bucket.arn_for_objects('*'),
                                    self.__clean_bucket.bucket_arn
                                ]))

        self.__s3role.add_to_principal_policy(
            iam.PolicyStatement(actions=[
                'glue:CreateDatabase', 'glue:CreateDatabase',
                'glue:DeleteDatabase', 'glue:GetDatabase', 'glue:GetDatabases',
                'glue:UpdateDatabase', 'glue:CreateTable', 'glue:DeleteTable',
                'glue:BatchDeleteTable', 'glue:UpdateTable', 'glue:GetTable',
                'glue:GetTables', 'glue:BatchCreatePartition',
                'glue:CreatePartition', 'glue:DeletePartition',
                'glue:BatchDeletePartition', 'glue:UpdatePartition',
                'glue:GetPartition', 'glue:GetPartitions',
                'glue:BatchGetPartition'
            ],
                                resources=['*']))

        self.__roles_list = [self.__s3role]

        self.__redshift_cluster = redshift.Cluster(
            self,
            "redshift",
            master_user=self.__master_user,
            vpc=vpc,
            cluster_name="ara-cdk-cluster",
            cluster_type=ClusterType.MULTI_NODE,
            default_database_name=_config.RedshiftDeploy.REDSHIFT_DB_NAME,
            encrypted=None,
            encryption_key=None,
            logging_bucket=None,
            logging_key_prefix=None,
            node_type=NodeType.DC2_LARGE,
            number_of_nodes=2,
            parameter_group=None,
            port=None,
            preferred_maintenance_window=None,
            removal_policy=RemovalPolicy.DESTROY,
            roles=self.__roles_list,
            security_groups=self.__security_groups_list,
            vpc_subnets=self.__subnets_selection,
        )

        self.__redshift_endpoint = self.__redshift_cluster.cluster_endpoint
    def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)
        self.current_dir = os.path.dirname(__file__)

        self.vpc = ec2.Vpc(self,
                           "VPC",
                           cidr="10.0.0.0/21",
                           max_azs=3,
                           subnet_configuration=[
                               ec2.SubnetConfiguration(
                                   cidr_mask=28,
                                   name="Database",
                                   subnet_type=ec2.SubnetType.ISOLATED,
                               )
                           ])

        self.vpc.add_interface_endpoint(
            "redshift_endpoint",
            service=ec2.InterfaceVpcEndpointAwsService("redshift"))

        self.vpc.add_interface_endpoint(
            "rds_endpoint", service=ec2.InterfaceVpcEndpointAwsService("rds"))

        self.redshift_secret = secrets.Secret(
            self,
            'redshift-admin',
            secret_name='redshift-admin',
            description=
            "This secret has generated admin secret password for Redshift cluster",
            generate_secret_string=secrets.SecretStringGenerator(
                secret_string_template='{"username": "******"}',
                generate_string_key='password',
                password_length=32,
                exclude_characters='"@\\\/',
                exclude_punctuation=True))

        self.redshift_cluster = redshift.Cluster(
            self,
            "datasource-redshift",
            master_user=redshift.Login(
                master_username="******",
                master_password=self.redshift_secret.secret_value_from_json(
                    'password')),
            vpc=self.vpc,
            vpc_subnets=ec2.SubnetSelection(
                subnet_type=ec2.SubnetType.ISOLATED))

        self.rds_secret = secrets.Secret(
            self,
            'rds-admin',
            secret_name='rds-admin',
            description=
            "This secret has generated admin secret password for RDS cluster",
            generate_secret_string=secrets.SecretStringGenerator(
                secret_string_template='{"username": "******"}',
                generate_string_key='password',
                password_length=32,
                exclude_characters='"@\\\/',
                exclude_punctuation=True))

        self.rds_cluster = rds.DatabaseCluster(
            self,
            "datasource-rds",
            engine=rds.DatabaseClusterEngine.aurora_mysql(
                version=rds.AuroraMysqlEngineVersion.VER_2_08_1),
            instance_props={
                "vpc_subnets": {
                    "subnet_type": ec2.SubnetType.ISOLATED
                },
                "vpc": self.vpc
            },
            credentials=rds.Credentials.from_secret(self.rds_secret))

        core.CfnOutput(self, "vpcId", value=self.vpc.vpc_id)
        core.CfnOutput(self, "redshiftUsername", value="admin")
        core.CfnOutput(self,
                       "redshiftPassword",
                       value=self.redshift_secret.secret_name)
        core.CfnOutput(self,
                       "redshiftClusterId",
                       value=self.redshift_cluster.cluster_name)
        core.CfnOutput(self,
                       "redshiftHost",
                       value=self.redshift_cluster.cluster_endpoint.hostname)
        core.CfnOutput(self, "redshiftDB", value="dev")
        core.CfnOutput(self, "rdsUsername", value="admin")
        core.CfnOutput(self, "rdsPassword", value=self.rds_secret.secret_name)
        core.CfnOutput(self,
                       "rdsClusterId",
                       value=self.rds_cluster.cluster_identifier)
        core.CfnOutput(self, "namespace", value="default")
        core.CfnOutput(self, "version", value="1")
Esempio n. 10
0
    def __init__(self, scope: core.Construct, id: str, vpc, props, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        # create s3 bucket that redshift will use. if this bucket exists
        # this cdk app will fail, so ensure this has not been created yet

        redshift_bucket = s3.Bucket(
            self,
            "mwaa-redshift import",
            bucket_name=f"{props['redshifts3location'].lower()}",
            versioned=True,
            block_public_access=s3.BlockPublicAccess.BLOCK_ALL
        )

        # create the files folder in the bucket - this is empty but needed in the DAG

        s3deploy.BucketDeployment(self, "File",
        sources=[s3deploy.Source.asset("./files")],
        destination_bucket=redshift_bucket,
        destination_key_prefix="files/",
        prune=False,
        retain_on_delete=False
        )

        redshift_bucket_arn = redshift_bucket.bucket_arn

        # get arn of dags bucket - not sure if this is needed so may remove
        
        dags_bucket = s3.Bucket.from_bucket_name(self, "mwaa-dag-bucket", f"{props['mwaadag'].lower()}")
        dags_bucket_arn = dags_bucket.bucket_arn

        # create redshift secret and redshift user

        # create redshift iam role/policy that we will attach to the RedShift cluster
        # that has the right level of access to a specific S3 bucket
        # you can further lockdown this policy by just specifying s3 actions.

        mwaa_redshift_policy_document = iam.PolicyDocument(
            statements=[
                iam.PolicyStatement(
                    actions=[
                        "s3:*"
                    ],
                    effect=iam.Effect.ALLOW,
                    resources=[
                        f"{redshift_bucket_arn}/*",
                        f"{redshift_bucket_arn}",
                        f"{dags_bucket_arn}/*",
                        f"{dags_bucket_arn}",
                        ]
                )
            ]
        )

        mwaa_redshift_service_role = iam.Role(
            self,
            "mwaa-redshift-service-role2nd",
            assumed_by=iam.ServicePrincipal("redshift.amazonaws.com"),
            inline_policies={"mwaaRedshiftPolicyDocument": mwaa_redshift_policy_document}
        )

        mwaa_redshift_service_role_arn = mwaa_redshift_service_role.role_arn

        # Setup Security Group

        default_redshift_security_group = ec2.SecurityGroup.from_security_group_id(
            self,
            "MWAARedshiftSG",
            security_group_id=vpc.vpc_default_security_group
            )

        default_redshift_security_group.add_ingress_rule(
            peer=default_redshift_security_group,
            connection=ec2.Port.tcp(5439)
            )

        # Modify MWAA security group to enable Redshift access

        mwaa_security_group = ec2.SecurityGroup.from_security_group_id(
            self,
            "SG",
            props['mwaa-sg']
            #mutable=False
            )
        mwaa_security_group.add_ingress_rule(ec2.Peer.any_ipv4(), ec2.Port.tcp(5439), "allow redshift access")
        

        # create subnet groups - one for RedShift and one for the VPE we will create
        # the VPE subnet will take in parameters we provide that are the subnet-ids
        # of the VPC where MWAA is deployed

        redshift_cluster_subnet_group = redshift.ClusterSubnetGroup(
            self,
            "RedshiftCSG",
            vpc = vpc,
            #vpc_subnets = ec2.SubnetSelection(subnets=vpc.private_subnets),
            vpc_subnets = ec2.SubnetSelection(subnet_type=ec2.SubnetType.PRIVATE),
            description="Redshift Cluster Subnet Group"
        )

        ## get all the subnet ids from the MWAA VPC

        subnet_ids = []
        mwaavpc = ec2.Vpc.from_lookup(
            self,
            "MWAA VPC",
            vpc_id=props['mwaa-vpc-id']
        )
        for subnet in mwaavpc.private_subnets:
            subnet_ids.append(subnet.subnet_id)
        for subnet in mwaavpc.public_subnets:
            subnet_ids.append(subnet.subnet_id)
        
        vpe_redshift_cluster_subnet_group = redshift.CfnClusterSubnetGroup(
            self,
            "MWAAVPERedshiftCSG",
            subnet_ids = subnet_ids,
            description="MWAA VPE Redshift Cluster Subnet Group"
        )

        redshiftclustername = f"{props['redshiftclustername'].lower()}"

        cluster = redshift.Cluster(
            self,
            "MWAARedshiftCluster",
             master_user=redshift.Login(
                master_username=props['redshiftusername']
            ),
            vpc = vpc,
            security_groups=[default_redshift_security_group],
            node_type=redshift.NodeType.RA3_4XLARGE,
            number_of_nodes=2,
            cluster_name=redshiftclustername,
            default_database_name=props['redshiftdb'],
            removal_policy=core.RemovalPolicy.DESTROY,
            roles=[mwaa_redshift_service_role],
            publicly_accessible=False,
            subnet_group=redshift_cluster_subnet_group
        )

        redshift_secret_arn = cluster.secret.secret_arn
        

        # Display some useful output

        core.CfnOutput(
            self,
            id="RedshiftSecretARN :",
            value=redshift_secret_arn,
            description="This is the Redshift Secret ARN"
        )

        core.CfnOutput(
            self,
            id="RedshiftIAMARN :",
            value=mwaa_redshift_service_role_arn,
            description="This is the Redshift IAM ARN"
        )

        core.CfnOutput(
            self,
            id="RedshiftClusterEndpoint :",
            value=cluster.cluster_endpoint.hostname,
            description="This is the Redshift Cluster Endpoint"
        )
        core.CfnOutput(
            self,
            id="MWAAVPCESG :",
            value=vpe_redshift_cluster_subnet_group.ref,
            description="This is the VPE Subnet Group to use when creating the VPC Endpoint"
        )
        core.CfnOutput(
            self,
            id="redshiftvpcendpointcli",
            value="aws redshift create-endpoint-access --cluster-identifier "+redshiftclustername+" --resource-owner "+self.account+ " --endpoint-name mwaa-redshift-endpoint --subnet-group-name "+vpe_redshift_cluster_subnet_group.ref+" --vpc-security-group-ids "+props['mwaa-sg'],
            description="Use this command to create your vpce"
        )        
 def _setup_redshift(self) -> None:
     port = 5439
     database = "test"
     schema = "public"
     redshift_role = iam.Role(
         self,
         "aws-data-wrangler-redshift-role",
         assumed_by=iam.ServicePrincipal("redshift.amazonaws.com"),
         inline_policies={
             "KMS":
             iam.PolicyDocument(statements=[
                 iam.PolicyStatement(
                     effect=iam.Effect.ALLOW,
                     actions=[
                         "kms:Encrypt",
                         "kms:Decrypt",
                         "kms:GenerateDataKey",
                     ],
                     resources=[self.key.key_arn],
                 )
             ]),
             "S3":
             iam.PolicyDocument(statements=[
                 iam.PolicyStatement(
                     effect=iam.Effect.ALLOW,
                     actions=[
                         "s3:Get*",
                         "s3:List*",
                         "s3:Put*",
                     ],
                     resources=[
                         self.bucket.bucket_arn,
                         f"{self.bucket.bucket_arn}/*",
                     ],
                 )
             ]),
             "LakeFormation":
             iam.PolicyDocument(statements=[
                 iam.PolicyStatement(
                     effect=iam.Effect.ALLOW,
                     actions=[
                         "lakeformation:GetDataAccess",
                         "lakeformation:GrantPermissions",
                         "lakeformation:GetWorkUnits",
                         "lakeformation:StartQueryPlanning",
                         "lakeformation:GetWorkUnitResults",
                         "lakeformation:GetQueryState",
                     ],
                     resources=["*"],
                 )
             ]),
             "Glue":
             iam.PolicyDocument(statements=[
                 iam.PolicyStatement(
                     effect=iam.Effect.ALLOW,
                     actions=[
                         "glue:SearchTables",
                         "glue:GetConnections",
                         "glue:GetDataCatalogEncryptionSettings",
                         "glue:GetTables",
                         "glue:GetTableVersions",
                         "glue:GetPartitions",
                         "glue:DeleteTableVersion",
                         "glue:BatchGetPartition",
                         "glue:GetDatabases",
                         "glue:GetTags",
                         "glue:GetTable",
                         "glue:GetDatabase",
                         "glue:GetPartition",
                         "glue:GetTableVersion",
                         "glue:GetConnection",
                         "glue:GetUserDefinedFunction",
                         "glue:GetUserDefinedFunctions",
                     ],
                     resources=["*"],
                 )
             ]),
         },
     )
     lf.CfnPermissions(
         self,
         "CodeBuildTestRoleLFPermissions",
         data_lake_principal=lf.CfnPermissions.DataLakePrincipalProperty(
             data_lake_principal_identifier=redshift_role.role_arn),
         resource=lf.CfnPermissions.ResourceProperty(
             table_resource=lf.CfnPermissions.TableResourceProperty(
                 database_name="aws_data_wrangler",
                 table_wildcard={},  # type: ignore
             )),
         permissions=[
             "SELECT", "ALTER", "DESCRIBE", "DROP", "DELETE", "INSERT"
         ],
     )
     redshift.ClusterSubnetGroup(
         self,
         "aws-data-wrangler-redshift-subnet-group",
         description="AWS Data Wrangler Test Arena - Redshift Subnet Group",
         vpc=self.vpc,
         vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
     )
     redshift_cluster = redshift.Cluster(
         self,
         "aws-data-wrangler-redshift-cluster",
         default_database_name=database,
         master_user=redshift.Login(
             master_username=self.db_username,
             master_password=self.db_password_secret,
         ),
         cluster_type=redshift.ClusterType.SINGLE_NODE,
         publicly_accessible=True,
         port=port,
         vpc=self.vpc,
         vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
         security_groups=[self.db_security_group],
         roles=[redshift_role],
     )
     glue.Connection(
         self,
         "aws-data-wrangler-redshift-glue-connection",
         description="Connect to Redshift.",
         type=glue.ConnectionType.JDBC,
         connection_name="aws-data-wrangler-redshift",
         properties={
             "JDBC_CONNECTION_URL":
             f"jdbc:redshift://{redshift_cluster.cluster_endpoint.hostname}:{port}/{database}",  # noqa: E501
             "USERNAME": self.db_username,
             "PASSWORD": self.db_password,
         },
         subnet=self.vpc.private_subnets[0],
         security_groups=[self.db_security_group],
     )
     secret = secrets.Secret(
         self,
         "aws-data-wrangler-redshift-secret",
         secret_name="aws-data-wrangler/redshift",
         description="Redshift credentials",
         generate_secret_string=secrets.SecretStringGenerator(
             generate_string_key="dummy",
             secret_string_template=json.dumps({
                 "username":
                 self.db_username,
                 "password":
                 self.db_password,
                 "engine":
                 "redshift",
                 "host":
                 redshift_cluster.cluster_endpoint.hostname,
                 "port":
                 port,
                 "dbClusterIdentifier":
                 redshift_cluster.cluster_name,
             }),
         ),
     )
     cdk.CfnOutput(self, "RedshiftSecretArn", value=secret.secret_arn)
     cdk.CfnOutput(self,
                   "RedshiftIdentifier",
                   value=redshift_cluster.cluster_name)
     cdk.CfnOutput(
         self,
         "RedshiftAddress",
         value=redshift_cluster.cluster_endpoint.hostname,
     )
     cdk.CfnOutput(self, "RedshiftPort", value=str(port))
     cdk.CfnOutput(self, "RedshiftDatabase", value=database)
     cdk.CfnOutput(self, "RedshiftSchema", value=schema)
     cdk.CfnOutput(self, "RedshiftRole", value=redshift_role.role_arn)
    def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)
        self.current_dir = os.path.dirname(__file__)

        self.quicksight_migration_source_assume_role = iam.Role(
            self, 'quicksight-migration-source-assume-role',
            description='Role for the Quicksight dashboard migration Lambdas to assume',
            role_name='quicksight-migration-source-assume-role',
            max_session_duration=core.Duration.seconds(3600),
            assumed_by=iam.ServicePrincipal('lambda.amazonaws.com'),
            inline_policies={
                'AllowAccess': iam.PolicyDocument(
                    statements=[
                        iam.PolicyStatement(
                            effect=iam.Effect.ALLOW,
                            actions=[
                                "quicksight:*",
                            ],
                            resources=["*"]
                        ),
                        iam.PolicyStatement(
                            effect=iam.Effect.ALLOW,
                            actions=[
                                "ssm:GetParameter",
                            ],
                            resources=["arn:aws:ssm:*:*:parameter/infra/config"]
                        )
                    ]
                )
            }
        )

        self.quicksight_migration_source_assume_role.assume_role_policy.add_statements(
            iam.PolicyStatement(
                effect=iam.Effect.ALLOW,
                actions=['sts:AssumeRole'],
                principals=[iam.AccountPrincipal("499080683179")]
            )
        )

        self.quicksight_migration_target_assume_role = iam.Role(
            self, 'quicksight-migration-target-assume-role',
            description='Role for the Quicksight dashboard migration Lambdas to assume',
            role_name='quicksight-migration-target-assume-role',
            max_session_duration=core.Duration.seconds(3600),
            assumed_by=iam.ServicePrincipal('lambda.amazonaws.com'),
            inline_policies={
                'AllowAccess': iam.PolicyDocument(
                    statements=[
                        iam.PolicyStatement(
                            effect=iam.Effect.ALLOW,
                            actions=[
                                "quicksight:*",
                            ],
                            resources=["*"]
                        ),
                        iam.PolicyStatement(
                            effect=iam.Effect.ALLOW,
                            actions=[
                                "ssm:GetParameter",
                            ],
                            resources=["arn:aws:ssm:*:*:parameter/infra/config"]
                        )
                    ]
                )
            }
        )

        self.quicksight_migration_target_assume_role.assume_role_policy.add_statements(
            iam.PolicyStatement(
                effect=iam.Effect.ALLOW,
                actions=['sts:AssumeRole'],
                principals=[iam.AccountPrincipal("499080683179")]
            )
        )

        self.vpc = ec2.Vpc(self, "VPC",
            cidr="10.0.0.0/21",
            max_azs=3,
            subnet_configuration=[
                ec2.SubnetConfiguration(
                    cidr_mask=28,
                    name="Database",
                    subnet_type=ec2.SubnetType.ISOLATED,
                )
            ]
        )

        self.vpc.add_interface_endpoint("redshift_endpoint",
            service=ec2.InterfaceVpcEndpointAwsService("redshift")
        )

        self.vpc.add_interface_endpoint("rds_endpoint",
            service=ec2.InterfaceVpcEndpointAwsService("rds")
        )

        self.redshift_secret = secrets.Secret(self,'redshift-admin',
            secret_name='redshift-admin',
            description="This secret has generated admin secret password for Redshift cluster",
            generate_secret_string=secrets.SecretStringGenerator(
                secret_string_template='{"username": "******"}',
                generate_string_key='password',
                password_length=32,
                exclude_characters='"@\\\/',
                exclude_punctuation=True
            )
        )

        self.redshift_cluster = redshift.Cluster(self, "datasource-redshift",
            master_user=redshift.Login(
                master_username="******",
                master_password=self.redshift_secret.secret_value_from_json('password')
            ),
            vpc=self.vpc,
            vpc_subnets=ec2.SubnetSelection(
                subnet_type=ec2.SubnetType.ISOLATED
            )
        )

        self.rds_secret = secrets.Secret(self,'rds-admin',
            secret_name='rds-admin',
            description="This secret has generated admin secret password for RDS cluster",
            generate_secret_string=secrets.SecretStringGenerator(
                secret_string_template='{"username": "******"}',
                generate_string_key='password',
                password_length=32,
                exclude_characters='"@\\\/',
                exclude_punctuation=True
            )
        )

        self.rds_cluster = rds.DatabaseCluster(self, "datasource-rds",
            engine=rds.DatabaseClusterEngine.aurora_mysql(
                version=rds.AuroraMysqlEngineVersion.VER_2_08_1),
            instance_props={
                "vpc_subnets": {
                    "subnet_type": ec2.SubnetType.ISOLATED
                },
                "vpc": self.vpc
            },
            credentials=rds.Credentials.from_secret(self.rds_secret)
        )

        ssm.StringParameter(self, 'InfraConfigParam',
                            parameter_name='/infra/config',
                            string_value=json.dumps(self.to_dict()))