Creating a Private MySQL instance with a Bastion Host using CDK & SSM

Collin Smith
7 min readApr 19, 2024

--

Introduction

In this article, we will show how to create a Private MySQL RDS instance with Secrets Manager in CDK with a Bastion Host using SSM

We will be using AWS CDK in Java to create this project but similar steps can be done in the language of your choice as well. The CDK code presented can be leveraged for other languages as the steps should be very similar.

By placing an RDS instance in a Private Subnet we are following best practices by avoiding public access to the RDS instance. This will require a bastion host that will allow people to access it via the public subnet. This is a best practices approach.

Business Case

The leprechauns love gold and to hide their treasure(sometimes at the end of rainbows). The want to build a treasure database to record their treasures and locations. This way they will not lose their treasure and can find it when they need it!

Architecture Diagram

Private MySQL RDS instance with a Bastion Host using CDK & SSM

Private MySQL RDS instance in custom VPC with Secrets Manager and Bastion Host

MySQL RDS instance deployed into a custom VPC in a private VPC

The above represents what will be deployed in this article. A custom VPC will be deployed with a public subnet and private subnet across 3 availability zones.

We are deploying a MySQL instance within one private subnet. It will be configured to use Secrets Manager for it’s credentials. Additionally a VPC Endpoint will be deployed so that Lambdas can reach the Secrets Manager credentials to authenticate to the RDS instance. An article will be written to show how to deploy a Spring Boot Application on AWS Lambda once we have deployed the above configuration.

Building the CDK Project

  1. Validate the Prerequisites (See the Appendix)

2. Create the CDK Project

cd c:\projects
mkdir javacdk-private-mysql
cd javacdk-private-mysql
cdk init app --language java

2. Open the project up in Eclipse

File -> Open Projects from File System

Your CDK Project should have the following structure based on the code found at https://github.com/collin-smith/javacdk-private-mysql. The key class to update is JavacdkPrivateMysqlStack.java which can be found in the repo just listed above.

Build the project and press Run as seen below(Right Click the Project in project explorer, Run As.., Maven Build.., Type “clean install” in the Goals field then press Run.)

It should then build as follows:

Make sure you have your environment setup properly to deploy to the correct account, region etc.

cd c:\projects\javacdk-private-mysql
cdk bootstrap
cdk synth
cdk deploy

After deploying the CDK app with “cdk deploy” you will see something like the following:

After “cdk deploy”

Looking in the AWS Console

We can see that a MySQL RDS instance has been created as follows:

MySQL RDS in a private subnet

Take note of the endpoint above as you will need that for when you want to log into the database with MySQL WorkBench.

We can also see that a Secrets Manager Secret was created that holds the credentials to the RDS instance

Bastion Host

As our RDS is located in a private VPC, we will use a bastion host to connect to the RDS database. This will be an EC2 instance that was created in a public subnet.

Bastion Host as seen in the console

Now to gain access to the Bastion host, we will start a session with AWS System Manager. See Start a session for more information.

We will run the following command with the right region, ec2 instance id, and RDS endpoint information. And ensure that you have configured your AWS environment correctly as well for the console session.

aws ssm start-session --region us-west-2 --target i-0f80a0c24bc489ba8 --document-name AWS-StartPortForwardingSessionToRemoteHost --parameters host="javacdkprivatemysqlstack-rds.cyxxifivnm0n.us-west-2.rds.amazonaws.com",portNumber="3306",localPortNumber="1053"

You should now see that a session has been started with your bastion host

** Note that I have changed the localPortNumber as I don’t want to conflict with my existing MySQL installation on my computer.

We are not allowing public access to the MySQL RDS instance but only from the bastion host as detailed in the Ingress rule below. If we have other services such as lambdas or EC2s then similar configurations can be done for them with ingress rules with security groups can be done.

Now you can configure the Bastion Host security group to only allow specific IP traffic that you determine.

databaseSecurityGroup.addIngressRule(bastionSecurityGroup, Port.tcp(3306), "MySQL From the bastion Security group");

Using the MySQL WorkBench database client

Open MySQL WorkBench, press Database -> Connect to Database . Enter the RDS endpoint in the hostname and enter in the username and password(Store in Vault …)

Note the username and password are found in the Secrets Manager Secret.

Let’s now create a database called leprechaun typing the command into the Query Tool and pressing the execute button (Lightning bolt)

CREATE DATABASE leprechaun;

We should then select the newly created database by executing the “USE leprechaun;” command

Now that we have the Query Tool open we can create our first table by executing the following script in the Query Tool

CREATE TABLE TREASURE
(
ID INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
DESCRIPTION VARCHAR(50),
LOCATION VARCHAR(600),
CREATED DATETIME
);

We should be able to insert records by executing the following command in the Query Tool

INSERT INTO TREASURE (DESCRIPTION, LOCATION, CREATED) VALUES ('POT OF GOLD', 'UNDER THE RAINBOW', NOW());

We should be able to query records by executing the following command in the Query Tool

SELECT * FROM TREASURE;

Now you have successfully created an RDS instance that you created with CDK and have created a database with a table.

If you wanted to create a spring boot lambda application to interact with this database please continue on to Creating a Spring Boot Java 21 application with a Public MySQL RDS

Tidying up

Once you have finished with your MySQL RDS instance please execute a “cdk destroy” to remove the resources.

cdk destroy

Conclusion

In this article, you have seen how you can create a Private Postgres RDS Instance with Secrets Manager with CDK & SSM. This was done using Java but the same principle can be done for any of the languages supported by CDK. With a Custom VPC you can create the right networking to help support the AWS workload that you want to create rather than rely on the default VPC.

As previously mentioned you can create a Spring Boot application to interact with this database at Creating a Spring Boot Java 21 application with a Private MySQL RDS

Now if you want to read on to other related to the concept of Java 21 Spring Boot with database implementations, please consider the following articles as well:

Appendix

Prerequisites

Access to an AWS Account

Java 21 — The latest Java version to date can be downloaded from here

Confirm that you have the right version in your command line

Eclipse IDE (or your other favorite Java IDE)

During installation from here, select “Eclipse IDE for Enterprise Java and Web Developers”

Note: If you have any issues with Eclipse supporting Java 21 you might need to install the following Marketplace Solution

AWS CLI(AWS Command Line Interface)

Install AWS CLI(AWS Command Line Interface) so that you can manage your AWS Service from your console.

https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html

Maven

A tool to help simplify the build processes in the Jakarta Turbine project. Install from here.

GIT

Git will allow you to do source control management. Install from here.

MySQL WorkBench

--

--

Collin Smith

AWS Ambassador/Solutions Architect/Ex-French Foreign Legion