rcmdnk's blog
Last update

PERMISSION DENIED (FIXING THE WORLD Book 2) (English Edition)

Macでたまにsshしたり、gitコマンドでGitHubにpushしたりするときに うまくいかない時があって色々調べたのでそのまとめ。

sshでPermission denined

普段Mac内でiTermなどターミナルを立ち上げて作業を行ってる時には問題ないんですが、 cronで予約しておいたジョブの中や Macに外からsshで入って作業したりするときに、 gitコマンドを使ったりすると、

Permission denied (publickey).
fatal: Could not read from remote repository.

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

こんな感じのエラーが。 同時にMacの方でターミナルなどを立ち上げて直接試してみると問題なく接続できます。

GitHub関連で調べていたらこんなページを見つけたので

Ref: Error: Permission denied (publickey)

これに従い取り敢えずMacの中でssh -vT [email protected]してみると

$ ssh -vT [email protected]
...
debug1: identity file /Users/user/.ssh/id_dsa type 2
debug1: identity file /Users/user/.ssh/id_dsa-cert type -1
...
debug1: Next authentication method: publickey
debug1: Offering RSA public key: /Users/user/.ssh/id_rsa
debug1: Server accepts key: pkalg ssh-rsa blen 279
debug1: Authentication succeeded (publickey).
...

と。何故かdsa鍵しか最初にみてませんが、最終的にrsa鍵で認証を通してます。

一方、外からssh(内部でssh localで入っても一緒の状態になりました)してからみると

$ ssh -vT [email protected]
...
debug1: identity file /Users/user/.ssh/id_dsa type 2
debug1: identity file /Users/user/.ssh/id_dsa-cert type -1
...
debug1: Next authentication method: publickey
debug1: Offering RSA public key: /Users/user/.ssh/id_rsa
debug1: Server accepts key: pkalg ssh-rsa blen 279
debug1: Authentication succeeded (publickey).

な感じで失敗。

~/.ssh/にはid_rsaもあるのを確認した上で、~/.ssh/configを見ると

Host github
  HostName github.com
  IdentityFile ~/.ssh/id_rsa
  User rcmdnk
  Compression yes

の記述はあり、GitHubではrsa鍵を使ってたので良いと思ったんですが、

追記: 2014/04/30

そもそもこれも間違い。 Hostgithubだけだとgithub.comに接続したときにこの部分も適用されません。

適用させるにはHost github.comとするかHost github*みたいにワイルドカードを使って 接続先のホスト名とマッチさせないといけません。

実際、上の状態でid_rsagithub_rsaとかに変更し、ファイルも移動させて試してみると

$ ssh -vT github.com
OpenSSH_6.2p2, OSSLShim 0.9.8r 8 Dec 2011
debug1: Reading configuration data /Users/USER/.ssh/config
debug1: Reading configuration data /etc/ssh_config
Debug1: /etc/ssh_config line 20: Applying options for *
...
debug1: Trying private key: /Users/USER/.ssh/id_rsa
debug1: Trying private key: /Users/USER/.ssh/id_dsa
debug1: No more authentication methods to try.
Permission denied (publickey).

みたいな感じで~/.ssh/configからは何も読み取ってないし キーもid_rsaの方を使ってます。

上の例では単にid_rsaとデフォルトのものを使ってたので通ってただけでした。。。

Host githubで通したいなら普段ssh接続するときも git clone git@github:rcmdnk/...みたいにしないといけません(逆にこのようにalias的にできる)。

ついでに、普段はこの様にgitというユーザーで使いますし、 githu.comで指定してたらHostNameの意味はないので

Host github.com
  IdentityFile ~/.ssh/github_rsa

だけでOK。id_rsaを使うならgithub自体の設定をconfigに書く必要もありません。

Compressionのオプションも環境によりますが、 よほど遅いネットワークでない限り気にすることないし 外しておいて良いかと。 (むしろ遅くなることもあるので)

追記ここまで

よく見たらその上の方に

Host *
  Protocol 2
  IdentityFile ~/.ssh/id_dsa

こんな記述が。。。昔どこかで使ったか、少なくとも今使っては居ないので、 なんかのテストで少し使っていたか、全く覚えてないですが、取り敢えずコメントアウト。 これが、ssh時にdsa鍵を強制してたのでいけなかったみたいで、 コメントアウトしたら外からsshした場合も

$ ssh -vT [email protected]
...
debug1: identity file /Users/user/.ssh/id_rsa type 1
debug1: identity file /Users/user/.ssh/id_rsa-cert type -1
debug1: identity file /Users/user/.ssh/id_dsa type 2
debug1: identity file /Users/user/.ssh/id_dsa-cert type -1
...
debug1: Next authentication method: publickey
debug1: Offering RSA public key: /Users/user/.ssh/id_rsa
debug1: PEM_read_PrivateKey failed
debug1: read PEM private key done: type <unknown>
Enter passphrase for key '/Users/user/.ssh/id_rsa':
debug1: read PEM private key done: type RSA
debug1: Authentication succeeded (publickey).
...

こんな感じでrsaキーを使ってOKに。 ただ、鍵にパスフレーズを入れてたみたいでこの場合パスフレーズを要求されました。 Mac内で行うときは聞かれない。

取り敢えずこれに関しては自分がおかしな設定残してただけで使えるようにはなったんですが、 なぜMac内で直接立ち上げたときは問題なかったのか意味不明だったのでちょっと調べてみることに。

Macでのssh-agent: launchdで立ち上げ

ssh-agentは特に気にしてなかったんですが、 Macではlaunchd を採用していてこれでssh-agentも管理されています。

設定ファイルは

/System/Library/LaunchAgents/org.openbsd.ssh-agent.plist

ターミナルを起動するとSSH_AUTH_SOCK

$ echo $SSH_AUTH_SOCK
/tmp/launchd-XXXXXX/Listeners

(XXXXXXの部分はランダムな文字列)と設定されてます。

追記: 2014/10/20

Mac OS X 10.10 Yosemiteからこのlaunchdのテンポラリーディレクトリの位置が変更されました。

Mac Yosemiteでの外部からログインしてssh-agentを正しく使う方法

追記ここまで

これでsshとかでこの値にアクセスしようとすると ssh-agentが起動するようになってるようです 1

さらに、この時に一度使った鍵のパスフレーズはKeyChainに保存される?ため 2 3 4 、 次回から起動した時は一度登録したパスフレーズは聞かれません。 で、上の場合Mac内ではssh-agentに鍵を最初の時に登録してあったのでパスフレーズも聞かれず上手く行ってた模様。

一方、外部からsshしたりしてSSH_AUTH_SOCKの値を見ると設定されてません。 これがどの部分で設定されてるかは結局良くわからなかったんですが、 取り敢えずこれが原因。

Macの方でこの値を取得して値だけ

$ export SSH_AUTH_SOCK=/tmp/launchd-XXXXXX/Listeners

とすれば、sshなどするときにssh-agentが自動で起動するようになりました。

SSH_AUTH_SOCKを自動で設定する

一番単純には/tmp/launchd*/Listenersを探して設定すればOK 5

export SSH_AUTH_SOCK=`ls -tr /tmp/launchd*/Listeners|tail -n1`

たまに該当するファイルが複数できてる事があるので 時間的に最後の物を選択。

この辺、どこで設定されてるか探し当てられませんでしたが、Macでログインした時に 新しいものが出来る模様。(launchdを勉強すれば分かるのだろうか。。。? SSH_AUTH_SOCKもMacでログインした時に 全体の環境変数として設定されてる?ログアウトしてログインし直したり 6すると新しい物が出来る。単に時間が経っても出来る?)

さらに、たまに上の方法で探した最後の物が間違ってる場合もあり(他の物様に作られたもの?)、上手く行かない時があるんですが、 webで探すとssh-agentで使われてる物を直接探して psから取ってきたり 7

export SSH_AUTH_SOCK=`ps auxeww | grep ssh-agent | grep SSH_AUTH_SOCK | sed 's/.*SSH_AUTH_SOCK=//' | cut -f 1 -d ' '`

lsofで探してきたり 8

export SSH_AUTH_SOCK=`/usr/sbin/lsof | grep Listeners | grep ssh-agent | awk '{print $8}'`

するものがありましたが、 ssh-agentが走ってないと駄目なので、例えばMacでログインだけして、 一度もMac内のターミナルからsshなどを実行してない状況で 他からsshしてくるとこれらは使えません。

なので、

.bashrc
1
2
3
4
5
6
7
8
9
10
11
12
13
# SSH_AUTH_SOCK
if [ "$SSH_AUTH_SOCK" = "" ];then
  sock_tmp=(`ls -t /tmp/launchd*/Listeners`)
  for s in ${sock_tmp[@]};do
    export SSH_AUTH_SOCK=$s
    ssh-add -l >& /dev/null
    if [ $? -eq 0 ];then
      break
    fi
    unset SSH_AUTH_SOCK
  done
  unset sock_tmp
fi

みたいな事を書いておくと正しい物を拾えます。

ただ、これでも、Macを起動しただけで一度もログインしてない状態だと うまくいかないので、その時は自分で別途ssh-agentを立ち上げるように すれば良いかも。 .bashrcを読み込んでるスクリプト起動時等に立ち上がるとパスフレーズを聞かれて止まってしまうので .bash_profileの方に

.bashrc_profile
1
2
3
4
5
6
7
8
9
if [ -f ~/.bashrc ] ; then
  . ~/.bashrc
fi
if [ "$SSH_AUTH_SOCK" = "" ];then
  eval `ssh-agent` > ~/.ssh-agent.tmp
  MY_SSH_AGENT_PID=`cat ~/.ssh-agent.tmp|cut -d" " -f3`
  rm -f ~/.ssh-agent.tmp
  ssh-add ~/.ssh/id_rsa
fi

と、.bashrc読み込み後にSSH_AUTH_SOCKが設定されてない時に限り ssh-agentを起動するように。

これだとssh-agentが増え続けるので、

.bashrc_logout
1
2
3
if [ "$MY_SSH_AGENT_PID" != "" ];
  kill -9 $MY_SSH_AGENT_PID
fi

と言った感じでログアウト時にkillするようにしておきます。

ただ、Macをサーバーの様に外から再起動させてそのまま置いておく、 ということはまず無いので、後半はやり過ぎで Listenersを探す程度にしておいて、 もし後半の様な状況で必要ならば手でssh-agentを起動する、 程度で良いかも。

Sponsored Links
  1. ただし、ssh-agent -lというMac特有のオプション?付きで起動: MacOSX & ssh-agent -l

  2. ssh-agent on Mac OS X 10.5 (Leopard)

  3. Diversion into MacOSX launchd & ssh-agent

  4. keychainでssh-agentと鍵を管理することにした

  5. Mac OS X の cron で SSH に失敗する.

  6. 普段ログインし直す必要なんて無いわけですが、LogMeInを使っていて、たまに調子悪いと勝手にログアウトしてしまうことがある。。。

  7. SSH Cheat Sheet

  8. where is SSH_AUTH_SOCK set?lsofの方は0.1秒程かかってちょっと遅い

Sponsored Links

« Brewall: brewパッケージを管理する Brewallにtapall追加 »

}