読者です 読者をやめる 読者になる 読者になる

Goldstine研究所

mosuke5's tech blog

SSHエージェントフォワード後に他のユーザでgit cloneする(鍵を使う)ことに関する考察

CentOS7 SSH エージェントフォワード sudo Linux

SSHのエージェントフォワードした後に、接続したユーザとは別のユーザでgit cloneしたいことがあった。
それについて調べていく中で学習したことや検討したことについてまとめた。

0. 前提

ローカルのPC(Mac)上で、Vagrantを使用してCentOS7の仮想サーバ(testsv)を立ち上げている。

<IPアドレス>
ローカルPC:192.168.33.1
仮想サーバ:192.168.33.100

本記事上での「git cloneする」とは、「プライベートのGitレポジトリからSSHを利用してクローンする」ということを指す。

1. SSHのエージェントフォワードを利用したい理由

まず、そもそもなぜSSHのエージェントフォワードをする必要があったのか。
最近では多くの方がご存知かつ利用していることだと思うが、仮想のサーバ上でgitを利用するときによく利用する。
(もちろんそれだけの用途ではありません)

仮想サーバを作るたびにSSHの鍵を生成して、Github等に登録するのが手間なので、
ローカルのPCの鍵を他のサーバへ引き継ぐことでgit clone等を可能にするのだ。

2. SSHエージェントフォワード利用時の挙動

SSHのエージェントフォワードで利用される認証情報は、接続先サーバの/tmp以下に保存されます。

[myuser@localpc ~]$ ssh -A vagrant@192.168.33.100
Last login: Sat Apr  4 xx:xx:xx 2015 from 192.168.33.1
[vagrant@testsv ~]$
[vagrant@testsv ~]$ ls -l /tmp | grep ssh
drwx------. 2 vagrant    vagrant    23  4月  4 11:35 ssh-skQVHsUCHU


また、接続ユーザにはSSH_AUTH_SOCKという環境変数ができ、どの認証情報を利用するか記述がされます。
実際に確認してみる。
確認方法は、envコマンドで環境変数一覧を表示し、そのなかで"ssh"を含むものをgrep

[vagrant@testsv ~]$ env | grep -i ssh
SSH_AUTH_SOCK=/tmp/ssh-skQVHsUCHU/agent.9034
SSH_CLIENT='192.168.33.1 58017 22'
SSH_CONNECTION='192.168.33.1 58017 192.168.33.100 22'
SSH_TTY=/dev/pts/0


ちなみにエージェントフォワードは、認証エージェントに登録されている秘密鍵
ログイン先のサーバから利用できるようにする機能であり、接続元自体が変わるわけではない。
試しにエージェントフォワードで接続したサーバ先から、更にsshをして、その接続状況をみてみる。

[myuser@localpc ~]$ ssh -A vagrant@192.168.33.100
Last login: Sat Apr  4 xx:xx:xx 2015 from 192.168.33.1
[vagrant@testsv ~]$ ssh -A vagrant@192.168.33.100
Last login: Sat Apr  4 xx:xx:xx 2015 from 192.168.33.1
[vagrant@testsv ~]$
[vagrant@testsv ~]$ w
 11:50:17 up  1:55,  2 users,  load average: 0.00, 0.01, 0.05
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
vagrant  pts/0    192.168.33.1     11:35    1.00s  0.04s  0.01s ssh -A vagrant@192.168.33.100
vagrant  pts/1    192.168.33.100   11:50    1.00s  0.01s  0.00s w

wコマンドの結果の3行目のFROMをみるとわかるが、接続元が変わるわけではない。

3. SSHエージェントフォワードで接続後にrootユーザでgit cloneする

例えば、rootでしかアクセスできないディレクトリにgit cloneしたいと思い、
以下のようにsudoをつけてgit cloneしてみる。

[vagrant@testsv ~]$ sudo git clone git@xxxxx.xxx:yyyy/zzzzzz.git /root/hoge
Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

sudoをつけてgit cloneしようとすると、エージェントフォワードしたのにアクセス権がありませんと言われてしまった。
なぜエージェントフォワードしたのにgit cloneできないのだろうか?

一般的な設定ではsudo実行すると、ユーザの環境変数はrootユーザへ引き継がれず、SSH_AUTH_SOCKがないことがわかる。
sudo後に環境変数がどうなっているか確認してみる。

[vagrant@testsv ~]$ sudo env | grep -i ssh
 (なにも表示されない)


sudo実行しても、SSH_AUTH_SOCKを引き継ぎたい!
実はsudoで環境変数を引き継ぐ方法がある。-Eのオプションを付けると環境変数を引き継ぐことが可能だ。
以下のようにsudo -Eとすると...

[vagrant@testsv ~]$ sudo -E env | grep -i ssh
SSH_CLIENT=192.168.33.100 60051 22
SSH_TTY=/dev/pts/1
SSH_AUTH_SOCK=/tmp/ssh-qhGLsXBURp/agent.9113
SSH_CONNECTION=192.168.33.100 60051 192.168.33.100 22


sudo -E環境変数が引き継げ、SSH_AUTH_SOCKが引き継げるので、-Eをつけてsudo git cloneをトライする。

[vagrant@testsv ~]$ sudo -E git clone git@xxxxx.xxx:yyyy/zzzzzz.git /root/hoge
Cloning into 'zzzzzz'...
remote: Counting objects: 27, done.
remote: Compressing objects: 100% (26/26), done.
remote: Total 27 (delta 13), reused 0 (delta 0)
Receiving objects: 100% (27/27), done.
Resolving deltas: 100% (13/13), done.
Checking connectivity... done.

予想通り成功しました!

(余談) suもsudoと同じ考え方ができる

sudoだけではなくsuでのユーザ切り替えについても同じことが言える。
rootユーザへ切り替えるとき、よくsu -とハイフンをつけると思う。
ハイフンをつけると、ログインシェルを使用してユーザを切り替えるので、環境変数の引き継ぎは行われない。

4. rootユーザでない他のユーザでgit cloneする

続いて、rootユーザではない別の一般ユーザでのgit cloneについて考える。
rootユーザの時と同じ要領で、sudoコマンドを利用しotheruserという別のユーザでgit cloneをしてみる。

まずは、sudoコマンドでは-uでユーザの指定ができるので、otheruserに切り替えた際の環境変数をみてみる。

[vagrant@testsv ~]$ sudo -E -u otheruser env | grep -i ssh
SSH_CLIENT=192.168.33.100 60051 22
SSH_TTY=/dev/pts/1
SSH_AUTH_SOCK=/tmp/ssh-qhGLsXBURp/agent.9113
SSH_CONNECTION=192.168.33.100 60051 192.168.33.100 22


rootの時と同様で予想通りな感じ。 SSH_AUTH_SOCKも引き継げているし、git clone可能だと思い以下を実行すると。

$ sudo -E -u otheruser git clone git@xxxxx.xxx:yyyy/zzzzzz.git /home/otheruser
Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.


rootユーザの時とは異なってgit cloneは不可…

でも理由はいたって簡単。
/tmp以下に保存されている認証情報は、所有者は接続したユーザでパーミッションは600なのだ。
つまり、otheruserではこの認証情報は読みこめないのである。

[vagrant@testsv ~]$ ls -l /tmp | grep ssh
drwx------. 2 vagrant    vagrant    23  4月  4 11:35 ssh-skQVHsUCHU

重要な情報なので、アクセス権は妥当ですよね。
試しにアクセス権を変えてみるとgit cloneは可能だ。

[vagrant@testsv ~]$ chmod -R 777 /tmp/ssh-skQVHsUCHU
[vagrant@testsv ~]$ sudo -E -u otheruser git clone git@xxxxx.xxx:yyyy/zzzzzz.git /home/otheruser
Cloning into 'zzzzzz'...
remote: Counting objects: 27, done.
remote: Compressing objects: 100% (26/26), done.
remote: Total 27 (delta 13), reused 0 (delta 0)
Receiving objects: 100% (27/27), done.
Resolving deltas: 100% (13/13), done.
Checking connectivity... done.

5. まとめ

SSHのエージェントフォワードした際の動きと、重要な観点については抑えられた。
SSHエージェントフォワードの仕組みを見ていくことで、
うかつにエージェントフォワードは利用してはいけない理由も見えてきた。

また、本題の「SSHエージェントフォワード後に、接続したユーザとは別のユーザでgit cloneしたい」だが、 そもそもそういうことをすることはNGということらしい。
別のもっと賢い方法を考えろってことのようでした。