I often know an EC2 instance ID and need to SSH to the server. In order to avoid manually looking up the IP address or hostname, I wrote a small script to let myself SSH to an EC2 given an instance ID.
I also frequently switch between 4-5 different AWS accounts and regions, with different private keys and AWS API keys, and most existing scripts I found do not support this. Below is my setup that allows me to quickly SSH to any EC2 server across all the accounts and regions.
The SSH Script
Filename: ssh-ec2
#!/usr/bin/env ruby require 'aws-sdk' profile = ARGV[0] ssh_command = ARGV[1] config = File.read("#{File.dirname(__FILE__)}/aws/#{profile}.profile") if !config puts "No config file found for #{profile}" exit end access_key_id = config.match(/AWS_ACCESS_KEY=(.+)/)[1] secret_access_key = config.match(/AWS_SECRET_KEY=(.+)/)[1] region = config.match(/EC2_REGION=(.+)/)[1] default_username = (m=config.match(/DEFAULT_USERNAME=(.+)/)) ? m[1] : 'ubuntu' AWS.config access_key_id: access_key_id, secret_access_key: secret_access_key, region: region if match=ssh_command.match(/(.+)@(.+)/) username = match[1] instance_id = match[2] else username = default_username instance_id = ssh_command end begin i = AWS.ec2.instances[instance_id] if i.public_dns_name puts "ssh -i ~/.ssh/#{profile}.aws.pem #{username}@#{i.public_dns_name}" system "ssh -i ~/.ssh/#{profile}.aws.pem #{username}@#{i.public_dns_name}" exit end rescue end puts "Could not find instance with id #{instance_id} on aws account #{profile}"
The Environment
A good place for this script is a "scripts" folder in your dotfiles repo which you can then add to your path, or if you don't have something like that set up, then just put it in your ~/.ssh/
folder and make a symlink to this script in /usr/local/bin/
.
In order to specify your AWS credentials and region, you'll need to make a folder containing your AWS credentials. Create a folder in the same folder as this script called aws
, and it will contain one file per AWS profile. The profile specifies the AWS account as well as the region.
For example:
. ├── aws │ ├── geoloqi.profile │ ├── geotrigger-production.profile │ ├── geotrigger-dev.profile │ └── esripdx.profile ├── ssh-ec2
Each of the *.profile
files looks like the below:
export AWS_ACCESS_KEY=XXXXXXXXX export AWS_SECRET_KEY=XXXXXXXXX export EC2_REGION=us-east-1
You should also ensure you name your SSH private keys to correspond to the profiles you have here. So for example I have a private key named ~/.ssh/esripdx.aws.pem
that I use to SSH to all the servers in that account and region. (See our project Blacksmith for a way to manage SSH keys for multiple users across multiple AWS accounts).
Once this is set up, you can SSH to a server as follows:
$ ssh-ec2 esripdx i-a3e8542d
The Shortcut
This is pretty good. But what if you want to type even fewer characters! This is where some clever bash aliases come in. I've defined short bash functions that help with this.
function ssh-p() { if [[ "$1" =~ i-[a-f0-9]+ ]] then ssh-ec2 geotrigger-production $1 else echo ssh -i geotrigger-production.aws.pem ubuntu@$1 ssh -i ~/.ssh/geotrigger-production.aws.pem ubuntu@$1 fi }
Now I can use this to either SSH to an instance ID, or use it to choose the proper private key when SSH'ing to a server by IP address.
$ ssh-p i-a3e8542d $ ssh-p 54.243.231.166