I love being a trainer for the AWS Advanced Operations course because I get to interact with people who already know Amazon Web Services, they have some experience on AWS and so they have pretty specific doubts and problems.

During these trainings I love the challenge of having to come up with a way of helping them out for something that is not “inmediately possible”, instead of saying “that’s not supported”.

So, I got the enquiry to copy an existing public key from one region to another.

AWS API has a method to import a public key: ImportKeyPair.
This accepts a public key in various forms, so you only need a way to get the public key.
“Easy! DescribeKeyPairs!” Wrong!
DescribeKeyPairs only returns a key fingerprint, and not the public key!

The Approach

From previous official AWS posts, with the BYOK (Bring Your Own Keypair) feature, you could use a common public key across regions, but you have to generate a new Public and Private Keypair, and I didn’t want to tell the student “change all your keys for new ones”

The thing is that the public key is not transmitted to us when AWS generates it.We only get the private key!

So knowing that the “I can’t get the public key” statement is false, I tried to work around it. The answer was in an operation we do almost every day: RunInstance.
AWS will expose the public key to an instance through the metadata service when it boots!

Solution

So back to work, and now that we’re at it… let’s try to automate it!
The strategy will be to launch an Amazon Linux AMI, upload ec2-user’s public key to all the regions via the ImportKeyPair.

{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"ec2:DescribeKeyPairs",
"ec2:DescribeRegions",
"ec2:ImportKeyPair"
],
"Effect": "Allow",
"Resource": "*"
}
]
}
sudo yum -f install aws-cli
# default region is needed for the describe-regions call. Get the region from metadata stripping off the az (last char)
export AWS_DEFAULT_REGION=`ec2-metadata -z | sed 's/placement: //' | sed 's/.$//'`
# keypair name the instance was launched with
export KEY_PAIR=`ec2-metadata -u | grep keyname | sed 's/^keyname://'`
# key content
export KEY=`cat /home/ec2-user/.ssh/authorized_keys`
# Invoke import-key-pair in all regions except the actual region (we can't overwrite an existing key)
aws --output=text ec2 describe-regions | cut -f3 | grep -v $AWS_DEFAULT_REGION | xargs -I{} aws --region {} ec2 import-key-pair --key-name $KEY_PAIR --public-key-material "$KEY"

Job done! Now, you can throw away your instance 🙂

*Disclaimer: This is my approach and applies to nearly all case scenarios, but I am not responsible for any damage you can cause in your infrastructure if you execute this before thinking if it is the right solution for your project.
If you have any doubts, feel free to ask and I will try to reply. I hope this little guide helped you, at least enlightening the path to your own solution.

TAGS: amazon web services, amazon web services, aws, aws, aws regions, byok, describekeypairs, keypairs, public key

speech-bubble-13-icon Created with Sketch.
Comments

Leave a Reply

Your email address will not be published. Required fields are marked *

*
*