项目作者: devopsrepohq

项目描述 :
Use this CDK stack to create a RDS instances and allow bastion host to access it.
高级语言: TypeScript
项目地址: git://github.com/devopsrepohq/rds.git
创建时间: 2020-08-01T09:38:52Z
项目社区:https://github.com/devopsrepohq/rds

开源协议:

下载


Use this CDK stack to create a RDS instances and allow bastion host to access it.

RDS architecture

What is it?

Amazon Relational Database Service (Amazon RDS) makes it easy to set up, operate, and scale a relational database in the cloud.

Features

  • Deploy a RDS Aurora Mysql instances
  • Use secrets manager to generate database password
  • Setup to allow bastion host to access it

Prerequisites

You will need the following before utilize this CDK stack:

Stack Explain

cdk.json

Define project-name and env context variables in cdk.json

  1. {
  2. "context": {
  3. "project-name": "container",
  4. "env": "dev",
  5. "profile": "devopsrepo"
  6. }
  7. }

lib/vpc-stack.ts

Setup standard VPC with public, private, and isolated subnets.

  1. const vpc = new ec2.Vpc(this, 'Vpc', {
  2. maxAzs: 3,
  3. natGateways: 1,
  4. cidr: '10.0.0.0/16',
  5. subnetConfiguration: [
  6. {
  7. cidrMask: 24,
  8. name: 'ingress',
  9. subnetType: ec2.SubnetType.PUBLIC,
  10. },
  11. {
  12. cidrMask: 24,
  13. name: 'application',
  14. subnetType: ec2.SubnetType.PRIVATE,
  15. },
  16. {
  17. cidrMask: 28,
  18. name: 'rds',
  19. subnetType: ec2.SubnetType.ISOLATED,
  20. }
  21. ]
  22. });
  • maxAzs - Define 3 AZs to use in this region.
  • natGateways - Create only 1 NAT Gateways/Instances.
  • cidr - Use ‘10.0.0.0/16’ CIDR range for the VPC.
  • subnetConfiguration - Build the public, private, and isolated subnet for each AZ.

Create flowlog and log the vpc traffic into cloudwatch

  1. vpc.addFlowLog('FlowLog');

lib/security-stack.ts

Get vpc create from vpc stack

  1. const { vpc } = props;

Create security group for bastion host

  1. const bastionSecurityGroup = new ec2.SecurityGroup(this, 'BastionSecurityGroup', {
  2. vpc: vpc,
  3. allowAllOutbound: true,
  4. description: 'Security group for bastion host',
  5. securityGroupName: 'BastionSecurityGroup'
  6. });
  • vpc - Use vpc created from vpc stack.
  • allowAllOutbound - Allow outbound rules for access internet
  • description - Description for security group
  • securityGroupName - Define the security group name

Allow ssh access to bastion host

  1. bastionSecurityGroup.addIngressRule(ec2.Peer.anyIpv4(), ec2.Port.tcp(22), 'SSH access');

lib/bastion-stack.ts

Get the vpc and bastionSecurityGroup from vpc and security stacks.

  1. const { vpc, bastionSecurityGroup } = props;

Create bastion host instance in public subnet

  1. const bastionHostLinux = new ec2.BastionHostLinux(this, 'BastionHostLinux', {
  2. vpc: vpc,
  3. securityGroup: bastionSecurityGroup,
  4. subnetSelection: {
  5. subnetType: ec2.SubnetType.PUBLIC
  6. }
  7. });
  • vpc - Use vpc created from vpc stack.
  • securityGroup - Use security group created from security stack.
  • subnetSelection - Create the instance in public subnet.

Display commands for connect bastion host using ec2 instance connect

  1. const createSshKeyCommand = 'ssh-keygen -t rsa -f my_rsa_key';
  2. const pushSshKeyCommand = `aws ec2-instance-connect send-ssh-public-key --region ${cdk.Aws.REGION} --instance-id ${bastionHostLinux.instanceId} --availability-zone ${bastionHostLinux.instanceAvailabilityZone} --instance-os-user ec2-user --ssh-public-key file://my_rsa_key.pub ${profile ? `--profile ${profile}` : ''}`;
  3. const sshCommand = `ssh -o "IdentitiesOnly=yes" -i my_rsa_key ec2-user@${bastionHostLinux.instancePublicDnsName}`;
  4. new cdk.CfnOutput(this, 'CreateSshKeyCommand', { value: createSshKeyCommand });
  5. new cdk.CfnOutput(this, 'PushSshKeyCommand', { value: pushSshKeyCommand });
  6. new cdk.CfnOutput(this, 'SshCommand', { value: sshCommand});

lib/rds-stack.ts

Get the vpc, bastionSecurityGroup, rdsKey from vpc, security and kms stacks

  1. const { vpc, bastionSecurityGroup, rdsKey } = props;

Get projectName and env from context variables

  1. const projectName = this.node.tryGetContext('project-name');
  2. const env = this.node.tryGetContext('env');

Create templated secret

  1. const templatedSecret = new secretsmanager.Secret(this, 'TemplatedSecret', {
  2. description: 'Templated secret used for RDS password',
  3. generateSecretString: {
  4. excludePunctuation: true,
  5. includeSpace: false,
  6. generateStringKey: 'password',
  7. passwordLength: 12,
  8. secretStringTemplate: JSON.stringify({ username: 'user' })
  9. },
  10. removalPolicy: cdk.RemovalPolicy.DESTROY
  11. });
  • description - Define the description for secrets manager template
  • generateSecretString - Define the secret constraint rule
  • removalPolicy - Remove this secrets manager template when removing this stack

Create RDS instances

  1. const cluster = new rds.DatabaseCluster(this, 'Database', {
  2. engine: rds.DatabaseClusterEngine.auroraMysql({
  3. version: rds.AuroraMysqlEngineVersion.VER_5_7_12
  4. }),
  5. instanceProps: {
  6. vpc: vpc,
  7. instanceType: ec2.InstanceType.of(ec2.InstanceClass.T3, ec2.InstanceSize.SMALL),
  8. vpcSubnets: {
  9. subnetType: ec2.SubnetType.ISOLATED
  10. }
  11. },
  12. masterUser: {
  13. username: 'admin',
  14. password: templatedSecret.secretValueFromJson('password')
  15. },
  16. defaultDatabaseName: `${projectName}${env}`,
  17. instances: 1,
  18. removalPolicy: cdk.RemovalPolicy.DESTROY,
  19. storageEncryptionKey: rdsKey
  20. });
  • engine - Specify to use aurora mysql engine version 5.7.12
  • instanceProps - Use T3.small instances and place it into isolated subnets
  • masterUser - Define db user and password
  • defaultDatabaseName - Define the default database name
  • instances - Define the number of instances for this aurora clusters
  • removalPolicy - Remove this rds cluster when removing this stack
  • storageEncryptionKey - Specify the encryption key for this aurora clusters

Allow bastion host to connect the RDS instances

  1. cluster.connections.allowDefaultPortFrom(bastionSecurityGroup, 'Allow access from bastion host');

Deploy all the stacks to your aws account.

  1. cdk deploy '*'
  2. or
  3. cdk deploy '*' --profile your_profile_name

Useful commands

NPM commands

  • npm run build compile typescript to js
  • npm run watch watch for changes and compile
  • npm run test perform the jest unit tests

Toolkit commands

  • cdk list (ls) Lists the stacks in the app
  • cdk synthesize (synth) Synthesizes and prints the CloudFormation template for the specified stack(s)
  • cdk bootstrap Deploys the CDK Toolkit stack, required to deploy stacks containing assets
  • cdk deploy Deploys the specified stack(s)
  • cdk deploy '*' Deploys all stacks at once
  • cdk destroy Destroys the specified stack(s)
  • cdk destroy '*' Destroys all stacks at once
  • cdk diff Compares the specified stack with the deployed stack or a local CloudFormation template
  • cdk metadata Displays metadata about the specified stack
  • cdk init Creates a new CDK project in the current directory from a specified template
  • cdk context Manages cached context values
  • cdk docs (doc) Opens the CDK API reference in your browser
  • cdk doctor Checks your CDK project for potential problems

Pricing

As this cdk stack will create Aurora database service, please refer the following link for pricing