🧩

Securely connect to an Amazon RDS using ECS Fargate as a bastion

2023/02/25に公開

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 --targetargument.

$ 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).

https://twitter.com/fujiwara/status/1591984494520606720

$ /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