exanubes
Q&A

Connecting to private RDS cluster via Bastion Host

When developing an infrastructure, sometimes we need to gain access to the production database, however, for security reasons databases are usually located in a private VPC without access to the internet. In order to gain access, we need to have a computer in the VPC that’s able to access the database and relay that connection to us.

Following up from setup aurora serverless with cdk where we setup a VPC, serverless aurora cluster and a Bastion Host EC2 Instance, we can use that infrastructure to connect to the production database.

You can download code for this article from github

Accessing the Bastion Host

Using the aws CLI’s ec2-instance-connect we can send an ssh public key.

aws ec2-instance-connect send-ssh-public-key 
  --instance-id "bastion_host_instance_id" 
  --instance-os-user ec2-user 
  --availability-zone "bastion_host_az" 
  --ssh-public-key "file://~/.ssh/id_rsa.pub"

Go to AWS EC2 Console and get the id and availability zone of the Bastion host instance and replace the placeholders in the above script.

What the script does is say “Hey aws, I want to connect to this ec2 instance so push this public ssh key to it so I can access it”. Everything else are just arguments for specifying the configuration like instance id, user, availability zone and the ssh key that we want to send over.

Now that everything is set up for us to be able to access the bastion host, we can open an ssh tunnel and map the database domain name and port to a localhost and port on our machine.

ssh -v -N -L "local_port:database_private_domain:5432" 
  -o "UserKnownHostsFile=/dev/null" -o "StrictHostKeyChecking=no" 
  -o ProxyCommand="aws ssm start-session --target %h --document-name AWS-StartSSHSession --parameters portNumber=%p" 
  "ec2-user@bastion_host_instance_id"

To get this to work, you have to replace local_port, database_private_domain and bastion_host_instance_id.

In order to get the database private domain go to rds clusters and find the endpoint in Connectivity & security tab in cluster details

Database private domain name in aws console

Important to note

The ec2-instance-connect lasts for a limited amount of time - make sure to have both commands ready with all the placeholders replaced with appropriate information and use them in quick succession otherwise it could deny entry.

Connecting to database from IDE

In the Secrets Manager dashboard in AWS console, find the secret generated for the database service and retrieve secret value.

Database secret value

Having all this information use the username, password, dbname, port and engine to connect to the database in the IDE of your choice.

Connecting to database in IDE

Keep in mind that sometimes the password doesn’t work if copied directly from aws. Try pasting it somewhere else and copy it again.

Summary

In this article we’ve covered how to setup a connection with a bastion host using the AWS CLI and ec2-instance-connect service. Furthermore, we’ve learned that the connection is active for a short amount of time in which we have to open an ssh tunnel if we want to gain and maintain access to the private instance.

Taking it from there, we used the aws generated secret value to get credentials and connect to the database via the previously opened ssh tunnel and mapped database address to the local port.