失敗したやり方
同じサーバ内で複数のリポジトリを扱っていたので~/.ssh/config
に以下のような設定を書いて
Host repo-A
HostName github.com
User git
IdentityFile ~/.ssh/repoAkey
Host repo-B
HostName github.com
User git
IdentityFile ~/.ssh/repoBkey
gitリポジトリのorigin
をそれぞれrepo-A:<github_user_name>/repoA.git
、repo-B:<github_user_name>/repoB.git
としていた
これでうまくいっていたのだが、デプロイキーを入れ替えたら全く機能しなくなってしまってハマった
原因
原因はconfig
の設定にIdentityFile
を指定しても必ずしもそれが使われるわけではないことだった
sshは使える鍵をいろいろ試してみて適合したらログインするという方法をとっているがその試してみる順番が必ずしもIdentityFile
が一番ではない(!)ので、repoAにアクセスしようとしているときにrepoBkeyを先に試されるとrepoBkeyを使ってgithub.comに接続してしまい(repoBkeyもgithubのリポジトリに登録されているのでgithub.comとのアクセスに使えてしまう!)repoAをいじる権限がないよ!と怒られてしまうのだ
指定した鍵より先にssh-agentに登録されている鍵が使われてしまうようだ
ssh-agentにどの鍵が登録されているかはssh-add -L
で確認できる
ssh -T repo-A
してみると
Hi xxxxx/xxxxx! You've successfully authenticated, but GitHub does not provide shell access.
というメッセージが出るが、このxxxxの部分がrepoAならrepoAkeyが正しく使われていて、repoBならrepoBkeyが使われてしまっているということがわかる
対策
なので、正しくは
Host repo-A
HostName github.com
User git
IdentityFile ~/.ssh/repoAkey
IdentitiesOnly yes
Host repo-B
HostName github.com
User git
IdentityFile ~/.ssh/repoBkey
IdentitiesOnly yes
と、IdentitiesOnly
をつけてあげると良い
そうするとそこに指定された鍵しかトライしないので想定した動作が得られる
ただしこれはそのサーバに鍵が実在するときのパターンで、鍵をAgentForwardで持ってきてる場合は鍵を使う順番を明示的に指定する方法がない(?)ため、事前にssh-add
コマンドを使ってForwardする鍵を絞っておくくらいしか方法がなさそう
リポジトリごとのデプロイキーを使わないでユーザーに紐付けた鍵を使えばこのような問題は起きないのでAgentForwardで使うならそうした方がいいかもしれない