Retrieve Public ssh Key From EC2

A serverfault poster had a problem that I thought was a cool challenge. I had so much fun coming up with this answer, I figured I’d share it here as it demonstrates a few handy features of EC2.

Challenge

The basic need is to get the public ssh key from a keypair that exists inside of EC2. You don’t have access to the private key at the moment (but somebody else does or you will at a different location).

The AWS console and EC2 API do not let you ask for the public ssh key associated with a keypair. However, EC2 does pass the public ssh key to a new EC2 instance when you run it with a specific keypair.

The problem is that we don’t currently have the private key, so we can’t log in to the EC2 instance to get the public key. (Besides, if we did have the private key, we could extract the public key from it directly.)

Solution

I proposed creating a user-data script that sends the public ssh key to the EC2 instance console output. You can retrieve the console output without logging in to the EC2 instance.

Save the following code to a file named output-ssh-key.userdata on your local computer. DO NOT RUN THESE COMMANDS LOCALLY!

#!/bin/bash -ex
exec> >(tee /var/log/user-data.log|logger -t user -s 2>/dev/console) 2>&1
adminkey=$(GET instance-data/latest/meta-data/public-keys/ | 
  perl -ne 'print $1 if /^0=[^a-z0-9]*([-.@\w]*)/i')
cat <<EOF
SSHKEY:===================================================================
SSHKEY:HERE IS YOUR PUBLIC SSH KEY FOR KEYPAIR "$adminkey":
SSHKEY:$(cat /home/ubuntu/.ssh/authorized_keys)
SSHKEY:===================================================================
SSHKEY:Halting in 50min ($(date --date='+50 minutes' +"%Y-%m-%d %H:%M UTC"))
EOF
sleep 3000
halt

Run a stock Ubuntu 10.04 LTS instance with the above file as a user-data script. Specify the keypair for which you want to retrieve the public ssh key:

ec2-run-instances \
  --key YOURKEYPAIRHERE \
  --instance-type t1.micro \
  --instance-initiated-shutdown-behavior terminate \
  --user-data-file output-ssh-key.userdata \
  ami-ab36fbc2

Keep requesting the console output from the instance until it shows your public ssh key. Specify the instance id returned from the run-instances command:

ec2-get-console-output YOURINSTANCEID | grep SSHKEY: | cut -f3- -d:

Repeat the above command a couple times a minute and within 2-10 minutes you will get output like this:

===================================================================
HERE IS YOUR PUBLIC SSH KEY FOR KEYPAIR "erich":
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA6rn8cl41CkzaH4ZBhczOJZaR4xBBDI1Kelc2ivzVvCB
THcdJRWpDd5I5hY5W9qke9Tm4fH3KaUVndlcP0ORGvS3PAL4lTpkS4D4goMEFrwMO8BG0NoE8sf2U/7g
aUkdcrDC7jzKYdwleRCI3uibNXiSdeG6RotClAAp7pMflDVp5WjjECDZ+8Jzs2wasdTwQYPhiWSiNcfb
fS97QdtROf0AcoPWElZAgmabaDFBlvvzcqxQRjNp/zbpkFHZBSKp+Sm4+WsRuLu6TDe9lb2Ps0xvBp1F
THlJRUVKP2yeZbVioKnOsXcjLfoJ9TEL7EMnPYinBMIE3kAYw3FzZZFeX3Q== erich
===================================================================
Halting in 50min (2011-12-20 05:58 UTC)

The temporary instance will automatically terminate itself in under an hour, but you can terminate it yourself if you’d like to make sure that you aren’t charged more than the two cents this will cost to run.

Notes

  • If you currently have access to the private ssh key (not true in the above challenge) you can extract the public ssh key using a command like:

     ssh-keygen -y -f KEYFILE.pem
    

but that’s obviously not as fun.

  • There is no way to retrieve the private ssh key if you have lost it. To protect your security, Amazon EC2 does not store a copy of this. If you are looking to get access to an EC2 instance where you have lost the private ssh key, I recommend following the approach I wrote about in this article: https://alestic.com/2011/02/ec2-fix-ebs-root

  • In seemingly-related-but-not news, Scott Moser is working on an enhancement to cloud-init (used by Ubuntu on EC2, Amazon Linux, and perhaps others) so that the public ssh host keys are output to the console output on instance startup. This cool feature will allow us to add the ssh host keys to our local known_hosts files, safely avoiding that pesky “Are you sure you want to continue connecting (yes/no)?" warning.