Symphonious

Living in a state of accord.

Easy SSH Access to EC2 Hosts

We run a bunch of hosts on EC2 and while most just have the default DNS name, they all have a Name tag to identify their purpose. While there’s lots of automation setup via ansible, it is often still necessary to SSH directly into a particular box, especially while debugging issues.

I find it annoying to have to go log into the AWS console just to find the DNS name of the particular box I want so I’ve written a little script that searches for hosts based on the name tag and can then SSH into them.

It requires having the aws  utility setup and able to login, plus having jq installed.

#!/bin/bash
set -euo pipefail
HOST_NAME=${1:-}
RESPONSE=`aws ec2 describe-instances`
INSTANCES=`jq "[.Reservations[].Instances[] 
    | select(.State.Code == 16) 
    | select(.PublicDnsName != \"\") 
    | select((.Tags[] | select(.Key == \"Name\")).Value | test(\"$HOST_NAME\"))] 
    | sort_by((.Tags[] | select(.Key == \"Name\")).Value)" <<< "$RESPONSE"`
HOSTS=(`jq -r '.[].PublicDnsName' <<< "$INSTANCES"`)
HOST_COUNT=${#HOSTS[@]}
if (( $HOST_COUNT == 0 ))
then
 echo "No matching hosts"
 exit 1
elif (( $HOST_COUNT > 1 ))
then
 NAMES=(`jq -r '.[].Tags[] | select(.Key == "Name").Value' <<< "$INSTANCES"`)
 echo "Multiple matching hosts found: "
 NUM=1
 for NAME in ${NAMES[@]}
 do
    HOSTNAME=${HOSTS[$((NUM - 1))]}
    echo "$NUM: $NAME  ($HOSTNAME)"
    NUM=$((NUM + 1))
 done
 read -p "Enter the number of the host you meant: " -r SELECTION
 SELECTED_HOST=${HOSTS[$((SELECTION - 1))]}
 ssh $SELECTED_HOST
else 
 ssh ${HOSTS[0]}
fi

Run with awssh <name> where <name> is a regex that matches any Name tag.  Typically a substring match is simplest.  So to SSH to the Medalla testnet bootnode we run I’d just use awssh medalla-bootnode.

If more than one node matches it provides a list of the matching nodes, so to select one of the Medalla nodes I’d run awssh medalla then select from the resulting list.