Securely connect to an Amazon RDS using ECS Fargate as a bastion
When you need to access a private Amazon RDS from a local machine, it's typical to establish a connection using either a VPN or a bastion host. This post shows how to connect to a private RDS by utilizing ECS Fargate as a bastion host with the assistance of AWS Systems Manager(SSM) Session Manager's port forwarding feature.
Port Forwarding using AWS System Manager Session Manager
AWS SSM Session Manager provides shell access to EC2 instances that have the SSM Agent installed, and this feature is also used by ECS Exec(ECS version of docker exec
).
In addition to shell access, SSM Session Manager also provides SCP/SSH connections and the ability to forward ports. In this post, I'll show you how to use the Fargate task as a bastion to connect to an RDS using this port forwarding feature.
Prerequisites
Ensure that ECS Exec is configured for tasks that you intend to use as a port-forwarding bastion.
Using Amazon ECS Exec for debugging - Amazon Elastic Container Service
Amazon ECS Exec Checker on GitHub can assist in verifying and validating that your Fargate tasks meet the prerequisites for using the ECS Exec feature.
Connect to ECS Fargate using SSM Session Manager
When connecting to an EC2 instance using SSM Session Manager, you must specify the instance ID.
$ aws ssm start-session \
--target i-123
However, ECS Fargate tasks are not assigned instance IDs. Instead, you must specify ecs:ClusterName_TaskId_RuntimeId
as the --target
argument.
You can find the cluster name and task ID in the console.
To find the Runtime ID, use ECS:DescribeTasks API.
$ aws ecs describe-tasks \
--cluster test \
--task ae8bd3553e9247308fd488b268de766b
{
"tasks": [
{
...
"containers": [
{
"containerArn": "arn:aws:ecs:REGION:123456789012:container/test/ae8bd3553e9247308fd488b268de766b/80afabe0-62bc-4c7a-8fb3-b34eda3d5cb6",
"taskArn": "arn:aws:ecs:REGION:123456789012:task/test/ae8bd3553e9247308fd488b268de766b",
"name": "fargate-app",
"image": "public.ecr.aws/docker/library/httpd:latest",
"runtimeId": "ae8bd3553e9247308fd488b268de766b-3681984407",
"lastStatus": "RUNNING",
...
}
],
...
}
],
"failures": []
}
You can find a runtimeId
field inside containers
.
Next, concatenate the following with an underscore (_
):
- Cluster Name
- Task ID
- Runtime ID
Pass the concatenated string as --target
argument.
$ aws ssm start-session \
--target ecs:test_ae8bd3553e9247308fd488b268de766b_ae8bd3553e9247308fd488b268de766b-3681984407
Starting session with SessionId: xxx-0d8b5abb61b899597
#
When using ECS Exec, you must specify the following:
- Cluster Name
- Task ID
- Container Name
By examining the responses of the ECS:DescribeTasks
API, it's clear that this information can uniquely identify the runtime ID.
Connect to an Amazon RDS via ECS Fargate bastion using SSM Session Manager
Now that we have confirmed that we can establish a connection to ECS Fargate using SSM Session Manager, we only need to add the extra parameters for port forwarding.
$ aws ssm start-session \
--target ecs:CLUSTERNAME_TASKID_RUNTIMEID \
--document-name AWS-StartPortForwardingSessionToRemoteHost \
--parameters '{"host":["REMOTE_HOST"],"portNumber":["REMOTE_PORT"], "localPortNumber":["LOCAL_PORT"]}'
For the --parameters
argument, you must specify the host and port number of the remote system, such as an RDS endpoint.
If you only need to forward a port inside a container, run the following command:
$ aws ssm start-session \
--target ecs:CLUSTERNAME_TASKID_RUNTIMEID \
--document-name AWS-StartPortForwardingSession \
--parameters '{"portNumber":["REMOTE_PORT"], "localPortNumber":["LOCAL_PORT"]}'
ECS Fargate suported SSM Port Forwarding from November 2022
SSM remote host port forwarding has been supported since May 2022. However, it was not until November 2022 that Fargate's SSM agent was updated to a version that supports this feature(version >= 3.1.1374.0).
$ /managed-agents/execute-command/amazon-ssm-agent --version
SSM Agent version: 3.1.1732.0
This update has made it much easier to use Fargate tasks as bastions.
ECS tools to simplify ECS Port Forwarding
You can utilize the ECS tools created by @fujiwara to simplify Fargate SSM port forwarding process.
ecspresso
$ ecspresso exec \
--port-forward \
--local-port 8080 \
--port 80 \
--host github.com
ecsta
$ ecsta portforward \
--local-port=8080 \
--remote-port=80 \
--remote-host=github.com
Note
This is an English translation of ECS Fargateを踏み台にポートフォワードしてVPC内のRDSに接続する with the assistance of ChatGPT.
Discussion