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

SSH git AWS

複数のアカウントやプロジェクトでそれぞれ異なる SSH キーを使用している場合、キーの管理が複雑になりがちです。毎回秘密鍵オプションを指定して SSH CLI コマンドを実行するのも面倒です。

そこで今回は、ホストごとに SSH キーを管理する簡単でクリーンな方法を共有したいと思います。

TL;DR

ホストごとにキーをアサイン

端的に言うと、~/.ssh/config というファイルでホストごとの定義を追加することが出来ます。

.ssh/config - Syntax

Host CONNECTION_NAME
HostName HOST_NAME
IdentityFile SSH_KEY
User USER_NAME
Port PORT_NUM
  • CONNECTION_NAME: ssh コマンドに渡す名前。例:github.work
  • HOST_NAME: 実際のホストドメインまたは IP アドレス。例:github.com
  • SSH_KEY: キーのパス。例:~/.ssh/id_rsa_work
  • USER_NAME: ssh でログインするユーザー名。例:git
  • PORT_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.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

参考までに、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.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!これで、リモートリポジトリへの接続に割り当てられたキーが自動的に使用されます。

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 に追加しましょう。

EC2 Instance with EIP

 

EIP のアドレスを新しいホストへコピーペーストします:

Host tokyo-bastion
Hostname 52.193.31.148
User ec2-user
Port 22
IdentityFile ~/.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!

参考

COPYRIGHT © 2023 Kohei Ando