All open source labs

Open Source

rds-jumphost-session-manager

Connect to your private RDS DB using the session manager.

TypeScript6 stars

RDS Jumphost with Session Manager

Demo CDK project showing how to securely access an RDS database in a private subnet using AWS Session Manager port forwarding through an EC2 jumphost.

No SSH keys. No public IPs. No NAT gateway.

Architecture

┌─────────────────────────────────────────────────────────────────┐
│                            VPC                                   │
│  ┌──────────────────────────────────────────────────────────┐   │
│  │                 Private Isolated Subnet                   │   │
│  │                                                           │   │
│  │   ┌─────────────┐              ┌──────────────────┐      │   │
│  │   │ EC2 Jumphost│──────────────│  RDS PostgreSQL  │      │   │
│  │   │ (SSM Agent) │   Port 5432  │                  │      │   │
│  │   └─────────────┘              └──────────────────┘      │   │
│  │          │                                                │   │
│  │          │ SSM via VPC Endpoints                          │   │
│  │          ▼                                                │   │
│  │   ┌─────────────────────────────────────────────────┐    │   │
│  │   │ VPC Endpoints (Interface)                        │    │   │
│  │   │ - ssm                                            │    │   │
│  │   │ - ssmmessages                                    │    │   │
│  │   │ - ec2messages                                    │    │   │
│  │   └─────────────────────────────────────────────────┘    │   │
│  └──────────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────────┘
                              │
                              │ Session Manager Port Forward
                              ▼
                        ┌──────────┐
                        │ Local    │  localhost:5432 → RDS:5432
                        │ Machine  │
                        └──────────┘

Prerequisites

  1. AWS CLI v2

    aws --version  # Should be 2.x
    
  2. Session Manager Plugin

    # macOS
    brew install --cask session-manager-plugin
    
    # Or download from:
    # https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manager-working-with-install-plugin.html
    
  3. Node.js and pnpm

    node --version  # 18.x or later
    pnpm --version
    
  4. AWS Credentials configured with permissions for:

    • CloudFormation
    • EC2
    • RDS
    • SSM
    • Secrets Manager
    • VPC

Deploy

# Install dependencies
pnpm install

# Deploy the stack
pnpm cdk deploy

# Note the outputs - you'll need the instance ID and RDS endpoint

Connect to the Database

Option 1: Use the tunnel script (recommended)

# Start the tunnel (forwards localhost:5432 → RDS:5432)
./scripts/tunnel.sh

# In another terminal, connect with psql
psql -h localhost -p 5432 -U postgres -d demo

Option 2: Manual port forwarding

one-liner:

  # Get password from Secrets Manager and connect via psql
  DB_SECRET=$(aws secretsmanager get-secret-value \
    --secret-id $(aws cloudformation describe-stacks \
      --stack-name RdsJumphostSessionManagerStack \
      --query "Stacks[0].Outputs[?OutputKey=='DatabaseSecretArn'].OutputValue" \
      --output text) \
    --query SecretString --output text) && \
  PGPASSWORD=$(echo $DB_SECRET | jq -r .password) psql \
    -h localhost \
    -p 5432 \
    -U $(echo $DB_SECRET | jq -r .username) \
    -d postgres
    ```

```bash
# Get the instance ID and RDS endpoint from stack outputs
aws cloudformation describe-stacks \
  --stack-name RdsJumphostSessionManagerStack \
  --query 'Stacks[0].Outputs'

# Start port forwarding
aws ssm start-session \
  --target <INSTANCE_ID> \
  --document-name AWS-StartPortForwardingSessionToRemoteHost \
  --parameters '{"host":["<RDS_ENDPOINT>"],"portNumber":["5432"],"localPortNumber":["5432"]}'

Option 3: Connect directly from the jumphost

# Start a shell session on the jumphost
aws ssm start-session --target <INSTANCE_ID>

# Install PostgreSQL client (first time only)
sudo dnf install -y postgresql15

# Connect to RDS
psql -h <RDS_ENDPOINT> -U postgres -d demo

Get Database Password

The password is stored in AWS Secrets Manager:

# Get the secret ARN
SECRET_ARN=$(aws cloudformation describe-stacks \
  --stack-name RdsJumphostSessionManagerStack \
  --query "Stacks[0].Outputs[?OutputKey=='DatabaseSecretArn'].OutputValue" \
  --output text)

# Retrieve the password
aws secretsmanager get-secret-value \
  --secret-id "$SECRET_ARN" \
  --query SecretString \
  --output text | jq -r .password

Use with GUI Tools

Start the tunnel, then connect your favorite database tool to:

Setting Value
Host localhost
Port 5432
Database demo
Username postgres
Password (from Secrets Manager)

Works with: DBeaver, DataGrip, pgAdmin, TablePlus, etc.

Cleanup

pnpm cdk destroy

How It Works

  1. VPC Endpoints allow the EC2 instance to communicate with AWS Systems Manager without internet access (no NAT gateway needed)

  2. Session Manager creates an encrypted tunnel through the SSM service, not through the network

  3. Port Forwarding (AWS-StartPortForwardingSessionToRemoteHost) tunnels traffic from your local machine through the EC2 instance to the RDS endpoint

  4. Security Groups only allow traffic from the jumphost to RDS on port 5432

Cost Considerations

This demo uses cost-optimized resources:

Resource Type ~Monthly Cost
EC2 Jumphost t4g.micro ~$6
RDS PostgreSQL db.t4g.micro ~$12
VPC Endpoints (3x) Interface ~$22
Total ~$40/month

For production, consider:

  • Using NAT Gateway instead of VPC Endpoints (if you need other outbound traffic)
  • Right-sizing instances based on actual usage
  • Enabling RDS backups and multi-AZ

Useful Commands

# Synthesize CloudFormation template
pnpm cdk synth

# Compare deployed stack with current state
pnpm cdk diff

# Deploy with approval prompt
pnpm cdk deploy

# Destroy all resources
pnpm cdk destroy

Looking for more hands-on labs?

Everything we build in the open — CLIs, libraries, and infrastructure snippets.

Browse all repositories →