in lib/blog-redshift-vpc-stack.ts [14:115]
constructor(scope: cdk.App, id: string, props: RedshiftVpcStackProps) {
super(scope, id, props);
//create the vpc for Redshift
const redshift_vpc = new ec2.Vpc(this, 'redshift-vpc', {
cidr: '10.0.0.0/16',
maxAzs: 1,
subnetConfiguration: [
{
subnetType: ec2.SubnetType.PUBLIC,
name: 'redshift-subnet'
}
]
});
const redshift_subnet = redshift_vpc.selectSubnets({
subnetGroupName: 'redshift-subnet'
})
//security group for Redshift
const redshift_sg = new ec2.SecurityGroup(this, 'redshift-sg', {
vpc: redshift_vpc,
allowAllOutbound: true,
securityGroupName: 'redshift-sg',
description: 'redshift security group'
});
//add an ingress rule that self references the security group to allow Glue traffic
redshift_sg.addIngressRule(redshift_sg, ec2.Port.tcpRange(0, 65535), 'allow glue to connect to redshift')
//returns the subnet as a string to be used in the Glue Connection
function getSubnetIds() {
return redshift_vpc.selectSubnets({ subnetGroupName: 'redshift-subnet' }).subnetIds.toString()
}
//create s3 Endpoint for Glue Connection to use
const s3_endpoint = new ec2.GatewayVpcEndpoint(this, 'vpc-endpoint', {
vpc: redshift_vpc,
service: new ec2.GatewayVpcEndpointAwsService('s3'),
subnets: [
redshift_subnet
]
});
//Generate secret for Redshift Cluster
const red_secret = new sm.Secret(this, 'red-secret', {
generateSecretString: {
secretStringTemplate: JSON.stringify({ username: 'etladmin' }),
generateStringKey: 'password',
passwordLength: 16,
excludeCharacters: '/@\"\\\'',
excludePunctuation: true
},
});
//Grant Secrets Manager read permissions to Glue role
red_secret.grantRead(props.glueRoleGrantSecretRead);
//Create Redshift cluster
const redshift_cluster = new redshift.Cluster(this, 'redshift-covid-hiring', {
clusterName: 'cluster-covid-hiring',
clusterType: redshift.ClusterType.SINGLE_NODE,
defaultDatabaseName: 'db-covid-hiring',
nodeType: redshift.NodeType.DC2_LARGE,
masterUser: {
masterUsername: 'etladmin',
masterPassword: red_secret.secretValueFromJson('password')
},
vpc: redshift_vpc,
vpcSubnets: redshift_subnet,
publiclyAccessible: false,
securityGroups: [
redshift_sg
],
removalPolicy: cdk.RemovalPolicy.DESTROY,
})
//get the subnet ID for Glue Connection to use
const glue_sub = Subnet.fromSubnetAttributes(this, 'glue-sub', {
subnetId: getSubnetIds(),
availabilityZone: 'us-east-1a'
})
//redshift jdbc url
const redshift_jdbc_url = 'jdbc:redshift://'+redshift_cluster.clusterEndpoint.socketAddress+'/db-covid-hiring'
//create Glue Connection to Redshift after Redshift cluster is available
const red_connect = new glue.Connection(this, 'red-connect', {
type: glue.ConnectionType.JDBC,
connectionName: 'redshift-connect',
securityGroups: [
redshift_sg
],
subnet: glue_sub,
properties: {
JDBC_ENFORCE_SSL: 'FALSE',
JDBC_CONNECTION_URL: redshift_jdbc_url,
USERNAME: 'etladmin',
PASSWORD: `{{resolve:secretsmanager:${red_secret.secretName}:SecretString:password}}`
}
})
}