Securely connect to Amazon RDS using ECS container as bastion
The AWS blog has a post on how to securely connect to Amazon RDS using AWS Systems Manager (SSM) Session Manager from your local machine. It describes a method of using an EC2 instance within the same private subnet as the RDS instance as a bastion host, which enables secure access without exposing the database publicly.
But what if you don’t use EC2 and instead run your application on containers with Amazon ECS? While there isn’t official documentation for this specific scenario, you can use a similar approach to securely connect to a RDS instance in a container-based infrastructure from your local machine.
Using ECS container as bastion host
With ECS Exec, you can run commands or start an interactive shell on a container running in Amazon ECS. Under the hood, ECS Exec makes use of AWS Systems Manager (SSM) Session Manager to establish a secure connection to the container, without the need to expose inbound ports or use bastion hosts.
Instead of running commands or a shell with ECS Exec, we can use the Session Manager connection for port forwarding to a remote host. This means that instead of connecting to the database directly, we create a secure tunnel through the container to our RDS instance.
This diagram illustrates how the secure connection works:
- You initiate a Session Manager connection using AWS Systems Manager.
- AWS Systems Manager creates an encrypted tunnel between your computer and the ECS container.
- The ECS container, which runs in a private subnet, has direct access to the RDS instance.
- Using port forwarding through this secure tunnel, you can access the RDS instance on a local port.
Prerequisites
You’ll need the following set up before proceeding:
- The AWS CLI installed on your local machine and configured with appropriate credentials.
- The Session Manager plugin installed locally for establishing the secure connection.
- An ECS task running with ECS Exec enabled and the necessary IAM permissions to access the RDS instance.
- A command-line or GUI database client that you’d like to use.
Starting a Session Manager session to an ECS container
To start a session to an EC2 instance, using the AWS CLI you would use this command:
$ aws ssm start-session --target instance-id
However, for ECS containers, you’ll need to use a different format that combines your cluster name, task ID, and runtime ID with underscores:
ecs:<cluster_name>_<task_id>_<runtime_id>
You can find all these values in the ECS console or via the AWS CLI commands.
Create a remote port forwarding session
Now that you can use Session Manager to connect to an ECS container, you can start a port forwarding session:
-
Open a terminal and start a Session Manager session with the
AWS-StartPortForwardingSessionToRemoteHost
Systems Manager document. Replace the placeholders with your own values:<hostname>
: The hostname of your RDS instance.<remote_port>
: The port number of your RDS instance (e.g.,5432
for PostgreSQL).<local_port>
: The local port number to forward to (can be the same as remote_port).
$ aws ssm start-session \ --target ecs:<cluster_name>_<task_id>_<container_runtime_id> \ --document-name AWS-StartPortForwardingSessionToRemoteHost \ --parameters host="<hostname>",portNumber="<remote_port>",localPortNumber="<local_port>"
You should see something similar to:
Starting session with SessionId: <your_session_id> Port <local_port> opened for sessionId <your_session_id>. Waiting for connections...
Keep this terminal open.
-
With the port forwarding session active, you can now connect to your database using your preferred client. For example, if you have a PostgreSQL database and the
psql
utility installed locally:$ psql -h localhost -p 5432 -U your_user -d your_database
Alternatively, instead of authenticating with your database username and password, you can enable IAM database authentication on your RDS instance. This eliminates the need to store sensitive database passwords on your local machine and provides better security through AWS IAM access control.