Switch SSH Keys by Host

SSH git AWS

When we are using multiple SSH keys for our accounts and projects, key management could become challenging. Running the SSH CLI command with the secret key option every single time could also be tedious.

Today, I would like to share a clean and easy way to manage SSH keys by hosts.

TL;DR

How to Assign Keys to a Host

In short, we can add a ~/.ssh/config file and define each host.

.ssh/config - Syntax

Host CONNECTION_NAME
HostName HOST_NAME
IdentityFile SSH_KEY
User USER_NAME
Port PORT_NUM
  • CONNECTION_NAME: A name you will pass to run ssh. e.g. github.work
  • HOST_NAME: Actual host domain or IP. e.g. github.com
  • SSH_KEY: The path to your key. e.g. ~/.ssh/id_rsa_work
  • USER_NAME: The user name you ssh into. e.g. git
  • PORT_NUM: Usually 22

Now let's take a look at actual use cases.

Use Case 1 - Multiple Git Accounts

Let's pick the example where you have multiple git accounts and have registered a different secret key for each.

Generate a Key for Each Account

If you use different email addresses for each account, it would be easier to identify each one if you include the email in the comment.

In this example, let’s use _work and _personal suffixes for the key names.

# For a work account
$ ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa_work.pub -C "workie@email.com"
# For a personal account
$ ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa_personal.pub -C "foo@email.com"

Edit .ssh/config

Now, this is the core part of this management trick. We will define ssh hosts on the ssh/config file.

$ vim ~/.ssh/config

Host Setting Example

Host github.w
HostName github.com
IdentityFile ~/.ssh/id_rsa_work
User git
Port 22
Host github.p
HostName github.com
IdentityFile ~/.ssh/id_rsa_personal
User git
Port 22

Just in case you were wondering, the default key id_rsa would be used if you haven’t set any key for the git domain.

I won’t cover how to register an ssh key to the git remote. Once the editing is done, check the connection with the command below:

$ ssh github.w
# This is equivalent to below:
# ssh -i ~/.ssh/id_rsa_work git@github.com

If you successfully connected, let’s move on to the git repo config.

Edit .git/config

You can set the remote host either by directly editing .git/config or the Git CLI.

All you have to do is to replace git@github.com with the Host CONNECTION_NAME you defined on .ssh/config.

# Work Account
[remote "origin"]
url = github.w:workie/REPOSITORY.git
fetch = +refs/heads/*:refs/remotes/origin/*
# Personal Account
[remote "origin"]
url = github.p:foo/REPOSITORY.git
fetch = +refs/heads/*:refs/remotes/origin/*

Git CLI

# Update
$ git remote set-url origin github.w:workie/REPOSITORY.git
# Add
$ git remote add origin github.w:workie/REPOSITORY.git

Voila! Git will use the assigned keys for remote repo connections from now on.

Use Case 2 - SSH into an EC2 Bastion Host

Another example of an SSH connection is for an EC2 bastion host.

When you are running EC2 instances in a private subnet, you would probably add a bastion host in a public subnet through which you would be able to talk to the ones in the private subnet. (Side note: You can log in to the EC2 instance shell via SSM Session Manager or EC2 dashboard now. So no bastion hosts are required.)

Launch an EC2

When you launch an EC2 instance, make sure you assign a key pair.

Allocate an EIP and Associate It to the Instance

This is not mandatory. However, the default public IP address will change if you make changes such as the instance type, or Stop/Start (except Reboot) the instance. So, let’s make the IP persistent since EIP is free as long as it’s attached to an instance.

Add EIP to .ssh/config

Now, let's add the public IP of the EIP to our .ssh/config file.

EC2 Instance with EIP

 

Copy and paste the EIP address to the new host:

Host tokyo-bastion
Hostname 52.193.31.148
User ec2-user
Port 22
IdentityFile ~/.ssh/aws/tokyo_bastion.pem

Change the Key Permissions

As many of you know, AWS enforces you to change the permissions of your keys to make sure they are securely managed on your end.

If you run an ssh command without changing the permissions, you will get an error like the below:

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: UNPROTECTED PRIVATE KEY FILE! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0644 for '~/.ssh/aws/tokyo_bastion.pem' are too open.

To prevent this, you can simply run the following command to remove the read permissions from the group and anyone:

$ chmod 600 ~/.ssh/aws/tokyo_bastion.pem

SSH Into the Instance

Finally, we are ready to run the ssh command.

$ ssh tokyo-bastion
, #_
~\_ ####_ Amazon Linux 2023
~~ \_#####\
~~ \###|
~~ \#/ ___ https://aws.amazon.com/linux/amazon-linux-2023
~~ V~' '->
~~~ /
~~._. _/
_/ _/
_/m/'
[ec2-user@ip-172-31-45-46 ~]$

Beautiful. Now let it fly!

References

COPYRIGHT © 2023 Kohei Ando