Access an AWS RDS via a Bastion Host
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:
- A Key Pair
- A VPC with 2 Private and Public Subnets (Like this one maybe)
- SQL Workbench (other MySql client applications are available)
Which will look like this:
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 zonesResources:
DBSubnetGroup:
Type: AWS::RDS::DBSubnetGroup
Properties:
DBSubnetGroupDescription: RDS Subnet Group
SubnetIds: !Ref SubnetsCluster:
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 VpcIdBastion:
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…
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:
- https://thecattlecrew.net/2018/03/02/managing-your-aws-rds-instance-via-bastion-host/
- https://github.com/awslabs/aws-cloudformation-templates/blob/master/community/services/RDS/aurora-serverless/template.yml
Done
Please comment if you like the article or see any mistakes.