ホストごとに SSH キーを切り替える

複数のアカウントやプロジェクトでそれぞれ異なる SSH キーを使用している場合、キーの管理が複雑になりがちです。毎回秘密鍵オプションを指定して SSH CLI コマンドを実行するのも面倒です。
そこで今回は、ホストごとに SSH キーを管理する簡単でクリーンな方法を共有したいと思います。
TL;DR
ホストごとにキーをアサイン
端的に言うと、~/.ssh/config
というファイルでホストごとの定義を追加することが出来ます。
.ssh/config - Syntax
Host CONNECTION_NAMEHostName HOST_NAMEIdentityFile SSH_KEYUser USER_NAMEPort PORT_NUM
CONNECTION_NAME
: ssh コマンドに渡す名前。例:github.workHOST_NAME
: 実際のホストドメインまたは IP アドレス。例:github.comSSH_KEY
: キーのパス。例:~/.ssh/id_rsa_workUSER_NAME
: ssh でログインするユーザー名。例:gitPORT_NUM
: 通常は 22
実際のユースケースを見ていきましょう。
Use Case 1 - 複数の Git アカウント
まずは、複数の git アカウントがあり、それぞ れに異なる秘密鍵を登録している例です。
それぞれのアカウント用にキーを作成
アカウントごとに異なるメールアドレスを使用している場合は、コメントにメールアドレスを含めると、それぞれを特定しやすくなります。
この例では、キー名に _work
および _personal
サフィックスを使用します。
# 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"
.ssh/config 編集
さて、これがこの管理方法の核となる部分です。 ssh/config
ファイルで ssh ホストを定義します。
$ vim ~/.ssh/config
ホスト設定例
Host github.wHostName github.comIdentityFile ~/.ssh/id_rsa_workUser gitPort 22Host github.pHostName github.comIdentityFile ~/.ssh/id_rsa_personalUser gitPort 22
参考までに、git ドメインにキーを設定していない場合は、デフォルトのキー id_rsa
が使用されます。
ssh キーを git リモートに登録する方法については割愛します。編集が完了したら、以下のコマンドで接続を確認します。
$ ssh github.w# This is equivalent to:# ssh -i ~/.ssh/id_rsa_work git@github.com
接続に成功したら、git リポジトリの設定へ進みます。
.git/config 編集
.git/config を直接編集するか、Git CLI を使用することで、リモートホストを設定出来ます。
ここでは git@github.com
を .ssh/config で定義した Host の CONNECTION_NAME
に置き換えるだけです。
# Work Account[remote "origin"]url = github.w:workie/REPOSITORY.gitfetch = +refs/heads/*:refs/remotes/origin/*# Personal Account[remote "origin"]url = github.p:foo/REPOSITORY.gitfetch = +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!これで、リモートリポジトリへの接続に割り当てられたキーが自動的に使用されます。
Use Case 2 - EC2 要塞ホストへの SSH
もう一つの例として、EC2 要塞ホストへの SSH 接続を紹介します。
プライベートサブネットで EC2 インスタンスを走らせている場合、パブリックサブネットに要塞ホストを追加し、それを介してプライベートサブネット内のインスタンスと通信できるようにするのが一般的です。(補足:現在は SSM の Session Manager または EC2 のダッシュボードから EC2 インスタンスシェルにログインできるようになったので要塞ホストは必須ではありません。)
EC2 を起動
EC2 インスタンスを起動する時は、キーペアを割り当てる事を忘れずに。
EIP を割り当て、インスタンスへ紐付ける
これは必須ではありませんが、インスタンスタイプやインスタンスの停止・開始(再起動以外)などの変更を行うと、デフォルトのパブリック IP アドレスが変更されてしまいます。 EIP はインスタンスにアタッチされている限り無料なので、これを使って IP を永続化します。
EIP を .ssh/config へ追加
それでは、EIP のパブリック IP アドレスを .ssh/config
に追加しまし ょう。

EIP のアドレスを新しいホストへコピーペーストします:
Host tokyo-bastionHostname 52.193.31.148User ec2-userPort 22IdentityFile ~/.ssh/aws/tokyo_bastion.pem
キーのパーミッションを変更
ご存じの通り、AWS ではキーが安全に管理されている事を保障するため、パーミッションの変更を強制されます。
パーミッションを変更せずに ssh コマンドを実行すると、次のようなエラーが発生します:
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ WARNING: UNPROTECTED PRIVATE KEY FILE! @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@Permissions 0644 for '~/.ssh/aws/tokyo_bastion.pem' are too open.
これを解決する方法は、次のコマンドを実行してグループとすべてのユーザーの読み取り権限を削除するだけです。
$ chmod 600 ~/.ssh/aws/tokyo_bastion.pem
インスタンスへ SSH でログイン
これで、ssh コマンドを実行する準備が整いました。
$ ssh tokyo-bastion, #_~\_ ####_ Amazon Linux 2023~~ \_#####\~~ \###|~~ \#/ ___ https://aws.amazon.com/linux/amazon-linux-2023~~ V~' '->~~~ /~~._. _/_/ _/_/m/'[ec2-user@ip-172-31-45-46 ~]$
美しいですね。Now let it fly!