Skip to content

AWS Configuration

Configure AWS infrastructure for StormTunnel connections using EC2 and AWS Session Manager. The recommended setup is an SSM-managed EC2 connector instance that can reach private RDS databases and internal services inside your VPC.


Prerequisites

  • AWS account with appropriate permissions
  • AWS CLI installed and configured (aws configure)
  • StormTunnel installed on client machine
  • A private RDS database or internal service reachable from the connector instance subnet

Quick Start

# 1. Launch an EC2 connector instance with SSM permissions
aws ec2 run-instances \
  --image-id ami-0c55b159cbfafe1f0 \
  --instance-type t3.micro \
  --iam-instance-profile Name=AmazonSSMManagedInstanceCore \
  --security-group-ids sg-xxxxxxxxx \
  --subnet-id subnet-xxxxxxxxx \
  --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=stormtunnel-connector}]'

# 2. Wait 2-3 minutes for SSM Agent to register

# 3. Test Session Manager connection
aws ssm start-session --target i-xxxxxxxxxxxxxxxxx

EC2 Instance Setup

From AWS Console

  1. Launch Instance - EC2 Console > Launch Instance
  2. AMI - Amazon Linux 2023 or Ubuntu 24.04 (SSM Agent pre-installed)
  3. Instance type - t3.micro for dev, t3.small/medium for production
  4. IAM Role - Select or create role with AmazonSSMManagedInstanceCore
  5. Security Group - No inbound rules; outbound HTTPS for Session Manager and database egress to RDS
  6. Launch - No key pair needed for Session Manager

Place the instance in a subnet that can route to the private RDS endpoint. It does not need a public IP address when your VPC has the required Systems Manager connectivity.

Instance Type Recommendations

Use Case Type vCPU Memory ~Cost/mo
Development t3.micro 2 1 GB $7.50
Small team t3.small 2 2 GB $15
Production t3.medium 2 4 GB $30

IAM Configuration

Instance Role

The EC2 instance needs Session Manager permissions.

Create via CLI:

# Create trust policy
cat > ec2-trust-policy.json <<EOF
{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": {"Service": "ec2.amazonaws.com"},
    "Action": "sts:AssumeRole"
  }]
}
EOF

# Create role and attach policy
aws iam create-role \
  --role-name EC2-SSM-Role \
  --assume-role-policy-document file://ec2-trust-policy.json

aws iam attach-role-policy \
  --role-name EC2-SSM-Role \
  --policy-arn arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore

# Create instance profile
aws iam create-instance-profile --instance-profile-name EC2-SSM-Role
aws iam add-role-to-instance-profile \
  --instance-profile-name EC2-SSM-Role \
  --role-name EC2-SSM-Role

User IAM Policy

Users connecting via StormTunnel need these permissions:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": ["ssm:StartSession"],
            "Resource": ["arn:aws:ec2:*:*:instance/*"],
            "Condition": {
                "StringLike": {
                    "ssm:resourceTag/Environment": ["development", "staging"]
                }
            }
        },
        {
            "Effect": "Allow",
            "Action": ["ssm:StartSession"],
            "Resource": [
                "arn:aws:ssm:*:*:document/AWS-StartPortForwardingSession",
                "arn:aws:ssm:*:*:document/AWS-StartPortForwardingSessionToRemoteHost"
            ]
        },
        {
            "Effect": "Allow",
            "Action": ["ssm:TerminateSession"],
            "Resource": "arn:aws:ssm:*:*:session/${aws:username}-*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "ec2:DescribeInstances",
                "ssm:DescribeInstanceInformation",
                "ssm:GetConnectionStatus"
            ],
            "Resource": "*"
        }
    ]
}

SSM Agent

Verify Agent Status

Most AMIs include SSM Agent. Verify it's running:

Amazon Linux:

sudo systemctl status amazon-ssm-agent

Ubuntu:

sudo systemctl status snap.amazon-ssm-agent.amazon-ssm-agent

Check registration:

aws ssm describe-instance-information
# Look for: PingStatus: Online

If the instance doesn't appear, wait 2-3 minutes or check:

  • IAM role attached to instance
  • Security group allows outbound HTTPS (443)
  • Agent logs: sudo tail -f /var/log/amazon/ssm/amazon-ssm-agent.log

Security Groups

No inbound rules needed -- Session Manager initiates connections from inside the instance.

# Create security group
aws ec2 create-security-group \
  --group-name ssm-tunnel-sg \
  --description "Session Manager tunnel access only" \
  --vpc-id vpc-xxxxxxxxx

# Only outbound HTTPS needed
aws ec2 authorize-security-group-egress \
  --group-id sg-xxxxxxxxx \
  --protocol tcp \
  --port 443 \
  --cidr 0.0.0.0/0

For private RDS access, the RDS security group must allow inbound database traffic from the connector instance security group:

aws ec2 authorize-security-group-ingress \
  --group-id sg-rdsxxxxxxxxx \
  --protocol tcp \
  --port 5432 \
  --source-group sg-connectorxxxxxxxxx

With Direct SSH (if needed)

# Add SSH inbound from your IP
MY_IP=$(curl -s https://checkip.amazonaws.com)
aws ec2 authorize-security-group-ingress \
  --group-id sg-xxxxxxxxx \
  --protocol tcp \
  --port 22 \
  --cidr ${MY_IP}/32

Testing

Test Session Manager

# List available instances
aws ssm describe-instance-information

# Start session
aws ssm start-session --target i-xxxxxxxxxxxxxxxxx

# Exit
exit

Test RDS Port Forwarding

# Forward local port 5432 to a private PostgreSQL RDS endpoint
aws ssm start-session \
  --target i-xxxxxxxxxxxxxxxxx \
  --document-name AWS-StartPortForwardingSessionToRemoteHost \
  --parameters '{"host":["mydb.abc123xyz.us-east-1.rds.amazonaws.com"],"portNumber":["5432"],"localPortNumber":["5432"]}'

# Test in another terminal
psql -h localhost -p 5432 -U postgres -d mydb

Test with StormTunnel

  1. Create new tunnel > AWS Session Manager
  2. Select region, AWS profile, and connector instance
  3. Set the remote host to the RDS endpoint and the remote port to the database port
  4. Connect

CloudWatch Logging

Enable session logging for audit and troubleshooting.

Via Console

  1. Systems Manager > Session Manager > Preferences
  2. Enable CloudWatch logging
  3. Log group: /aws/ssm/SessionManager

Via CLI

# Create log group
aws logs create-log-group --log-group-name /aws/ssm/SessionManager

# Query logs
aws logs tail /aws/ssm/SessionManager --follow

VPC Endpoints (Private Connectivity)

To keep SSM traffic off the public internet, use VPC endpoints:

VPC_ID="vpc-xxxxxxxxx"
SUBNET_IDS="subnet-xxxxxxxx,subnet-yyyyyyyy"
SG_ID="sg-xxxxxxxxx"

# Required endpoints
for service in ssm ssmmessages ec2messages; do
  aws ec2 create-vpc-endpoint \
    --vpc-id $VPC_ID \
    --vpc-endpoint-type Interface \
    --service-name com.amazonaws.us-east-1.$service \
    --subnet-ids $SUBNET_IDS \
    --security-group-ids $SG_ID
done

Troubleshooting

Instance Not in SSM

# Check IAM role
aws ec2 describe-instances \
  --instance-ids i-xxxxxxxxx \
  --query 'Reservations[0].Instances[0].IamInstanceProfile'

# Check agent status (on instance)
sudo systemctl status amazon-ssm-agent
sudo tail -f /var/log/amazon/ssm/amazon-ssm-agent.log

# Restart agent
sudo systemctl restart amazon-ssm-agent

"TargetNotConnected" Error

# Check SSM status
aws ssm describe-instance-information \
  --filters "Key=InstanceIds,Values=i-xxxxxxxxx"

# If offline, reboot instance
aws ec2 reboot-instances --instance-ids i-xxxxxxxxx

Port Forwarding Fails

# Connect first, then check service
aws ssm start-session --target i-xxxxxxxxx
sudo ss -tlnp | grep :5432  # Check if service running

Cost Overview

Session Manager itself has no additional charge.

Component Usage ~Cost
EC2 t3.micro 730 hours $7.50/mo
Data transfer 10 GB Free tier
CloudWatch Logs 1 GB $0.53/mo
Total ~$8/mo