Access an AWS RDS via a Bastion Host

ET Fairfax
3 min readFeb 19, 2019

--

So you’ve created an RDS Database, and are now wondering how the heck you can take a peek inside of the DB from your local machine.

Enter the Bastion Host

A bastion host is a special purpose computer on a network specifically designed and configured to withstand attacks. The computer generally hosts a single application, for example a proxy server, and all other services are removed or limited to reduce the threat to the computer.

Good practice will have us throw the RDS into a private subnet within our VPC. We’ll then use the bastion host to tunnel our way through to the RDS instance.

What you’ll need:

Which will look like this:

Proposed Architecture

Next, we’ll get all this defined in CloudFormation templates.

The DBCluster Template

This CF Template will create the RDS Cluster — In this case I’m going with the serverless option.

When creating this stack you’ll need to select the VPC and two private subnets in differing availability zones.

AWSTemplateFormatVersion: 2010–09–09Description: Aurora serverless clusterParameters:
DatabaseName:
Type: String
EngineVersion:
Type: String
Default: ‘5.6’
MasterUsername:
Type: String
Default: root
MasterUserPassword:
Type: String
NoEcho: true
VpcId:
Type: AWS::EC2::VPC::Id
VpcSecurityGroupId:
Type: AWS::EC2::SecurityGroup::Id
Subnets:
Type: List<AWS::EC2::Subnet::Id>
Description: At least two private subnets associated with at least two different availability zones
Resources:
DBSubnetGroup:
Type: AWS::RDS::DBSubnetGroup
Properties:
DBSubnetGroupDescription: RDS Subnet Group
SubnetIds: !Ref Subnets
Cluster:
Type: AWS::RDS::DBCluster
Properties:
BackupRetentionPeriod: 5
Engine: aurora
EngineMode: serverless
EngineVersion: !Ref EngineVersion
MasterUsername: !Ref MasterUsername
MasterUserPassword: !Ref MasterUserPassword
DBClusterIdentifier: !Ref AWS::StackName
DeletionProtection: true
DBSubnetGroupName: !Ref DBSubnetGroup

The Bastion Host Template

I like to keep this in a separate stack as I don’t really want this in production, but should I ever need to have a look in the production RDS, I can spin it up.

This time pick a public subnet.

AWSTemplateFormatVersion: 2010–09–09Description: Aurora serverless bastionParameters:
VpcId:
Type: AWS::EC2::VPC::Id
VpcSecurityGroupId:
Type: AWS::EC2::SecurityGroup::Id
SubnetId:
Type: AWS::EC2::Subnet::Id
Description: Public Subnet Id
BastionImageId:
Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
Default: /aws/service/ami-amazon-linux-latest/amzn-ami-hvm-x86_64-ebs
BastionKeyName:
Type: AWS::EC2::KeyPair::KeyName
Description: EC2 key used to connect to the bastion host

Resources:
BastionSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
Name: ${AWS::StackName}-securitygroup
GroupDescription: !Sub Bastion Security Group for ${AWS::StackName}
SecurityGroupEgress:
— CidrIp: 0.0.0.0/0
FromPort: -1
ToPort: -1
IpProtocol: ‘-1’
— DestinationSecurityGroupId: !Ref VpcSecurityGroupId
IpProtocol: tcp
FromPort: 3306
ToPort: 3306
SecurityGroupIngress: []
VpcId: !Ref VpcId
Bastion:
Type: AWS::EC2::Instance
Properties:
DisableApiTermination: false
ImageId: !Ref BastionImageId
InstanceType: t2.micro
KeyName: !Ref BastionKeyName
Monitoring: false
SecurityGroupIds:
— !Ref VpcSecurityGroupId
— !Ref BastionSecurityGroup
SubnetId: !Ref SubnetId
Tags:
— Key: name
Value: ${AWS::StackName}
UserData:
“Fn::Base64”:
!Sub |
#!/bin/bash
# Update all packages
yum -y update
# Install mysql client
yum -y install mysql — assumeyes

Update the bastion security group in EC2 allow ssh for your IP address

MySQL Workbench

Open MySQL and configure a new connection as shown here…

MySql Workbench Connection Config

SSH Username

  • Got to the EC2 Bastion Host instance in AWS Console
  • Right click the instant and click “Connect”
  • In the given example you will see something like ssh -i “rds-bastion.pem” ec2-user@ec2–11–22–33–456.eu-west-1.compute.amazonaws.com
  • The bit before the @ is your SSH Username.
  • If you’ve used the YML in this article, with the default ImageId, it will always be ec2-user

MySql Host Name

Your AWS RDS Database Endpoint

SSH Hostname

The Bastion Host AWS EC2 Instance Public DNS name

References

Thanks go to:

Done

Please comment if you like the article or see any mistakes.

--

--