プログラマーのメモ書き

伊勢在住のプログラマーが気になることを気ままにメモったブログです

Mac 版 SourceTree で SSH による Bitbucket のリポジトリが clone できない問題への対応

しばらく前に、 iOS アプリの仕事が入ったため Mac を調達することになりました。納期との関係でそろそろハードウェアを手配しないといけなくなったのですが、タイミング的に、 M1 搭載の機種だと、納品までに動作検証が確実にできるかちょっとわからなかったので、ここは泣く泣く Intel 版の Mac を購入しました。

で、今月 11 月のとある日に、納品されたので、あれこれとセットアップを始めたのですが、 SourceTree のセットアップ(というより SSH まわりの設定)でハマったので、メモを残したいと思います。

ちなみに、やりたかったことはシンプルで、

SourceTree を設定し、 Bitbucket のリポジトリに SSH でアクセスする

というだけです。

SourceTree のインストール

まず、 SourceTree のバイナリをダウンロードしてきます。

(ちなみに、ここで、Mac版 SourceTree のインストールの説明とか見ても、『 zip ファイルを解凍』などというのが見られるのに、 Safari でダウンロードすると .app ファイルしかないというところから、違和感たっぷりです。しばらくしてから zip ファイルは(安全なファイルとみなされるファイルというべきかな?)自動的に解凍されるという Safari のデフォルト設定があるのがわかって、やっと納得しました。)

解凍したファイルをダブルクリックして、あとはインストーラの指示に従ってセットアップを進めます。

この時、Windows 版と同様に、Atlassian アカウントを入力しています。

あとは細かく覚えてませんが、特に問題なくセットアップが終わりました。

リポジトリのクローン

インストール後 SourceTree を起動すると、先ほど入力した Atlassian カウントに紐づくリポジトリの一覧が表示されます。

さて、ここで疑問です。現在、 Bitbucket のリポジトリは、2段階認証を導入しているので、 SSH でのアクセスが必須です(下記参照)。

Enable two-step verification | Bitbucket Cloud | Atlassian Support

でも、 SSH のプライベートキーの設定など、何もやってない、というか、そもそも Mac 上にキーファイルのコピーすらしてないので、リポジトリが表示されるのはいいんだけど、さて、クローン出来るんだろうか?とおもってやってみると、やはりうまくできません。

で、 SSH キーを設定しようとしました。SourceTree の『環境設定』を開いて、『アカウント』タブを表示すると、インストール時に作った覚えがないんですが、何やら Bitbucket 用のアカウントが設定されています。

これを開くと、SSHキーの作成 はできそうなのですが、既に運用中の既存の SSH のプライベートキー を設定しようと思ったら、やり方がよくわからないです。

ついでに、Windows 版の SourceTree の設定と比べてみると、この部分(Windows版 3.3.8 だと、『ツール』->『オプション』->『認証』タブに該当しそうです)には特にアカウントが設定されていません。

ということで、一旦、既に登録済みのアカウントを削除して、SSH キーを設定してみることにしました。

既存の SSH キーを設定(公式の設定方法)

まあ、SourceTree の Mac 版で SSH キーが設定できないのは話にならないので、設定方法は簡単に見つかるだろうと思い、実際、ちょっと調べると、Atlassian のサイトに設定方法が載ってました。

Set up an SSH key | Bitbucket Cloud | Atlassian Support

さっそくやってみます。ただし、既にキーは持っているし、Bitbucketのサーバー側にパブリックキーも登録済みなので、上記記事の Step 1 と Step 3 は省略して、 Step 2 を実行します。

mor@JunichinoMac-mini ~ % cd .ssh 
mor@JunichinoMac-mini .ssh % eval `ssh-agent`
Agent pid 2958
mor@JunichinoMac-mini .ssh % ssh-add -K ~/.ssh/bitbucket.openssh.private
Identity added: /Users/mor/.ssh/bitbucket.openssh.private (/Users/mor/.ssh/bitbucket.openssh.private)
mor@JunichinoMac-mini .ssh % 
mor@JunichinoMac-mini .ssh % touch config
mor@JunichinoMac-mini .ssh % chmod 600 config 
mor@JunichinoMac-mini .ssh % vi config
mor@JunichinoMac-mini .ssh % cat config
Host *
    UseKeychain yes
mor@JunichinoMac-mini .ssh % 

設定後、一度 SourceTree で Bitbucket 上のリポジトリをクローンすると、うまくできました!

これで、一安心。

トラブル

と思いきや、一度ログアウトしてから、再度ログインして pull などを試すとうまくできません。

f:id:junichim:20201130152754p:plain

上記公式の説明の Step 3 にある確認方法を試すと、

mor@JunichinoMac-mini ~ % ssh -T git@bitbucket.org
git@bitbucket.org: Permission denied (publickey).
mor@JunichinoMac-mini ~ % 

となり、アクセスできないのが確認できました。 どうしたものかと思い、トラブルシュートがあるのでそれを見てみると、キーが登録されているか確認する、とあります。試します。

mor@JunichinoMac-mini ~ % ssh-add -l
The agent has no identities.
mor@JunichinoMac-mini ~ % 

なにも出てこないですね・・・

はい、もう一度やり直しですね。

理由

上記の公式の手順を試した際に、

mor@JunichinoMac-mini ~ % eval `ssh-agent`

って、何だろうと?違和感があったのですが、そのまま調べずに進めていました。改めて、 man ssh-agent を読むと、ssh-agent は ssh を利用するコマンドを最初に利用する際に、起動される、とあります。デーモンじゃないんだ!

ということは、登録したキーもログインセッション中のみ有効ということのようです。これで、ログインしなおしたら、リポジトリにアクセスできなくなる理由がわかりました。

SSH キーを恒久的に登録

毎回、公式の説明にあるような

ssh-add -K プライベートキーファイル

を実行するわけにはいきません。

たぶん、同じように困っている人はたくさんいるだろうからと思い、ちょっと調べてみると、

macos - SourceTree SSH options on OS X - Super User How can I permanently add my SSH private key to Keychain so it is automatically available to ssh? - Ask Different

にある方法でうまくいきそうです。

まとめると要は ~/.ssh に config ファイルを設定すればよいというものです。

mor@JunichinoMac-mini ~ % cd .ssh
mor@JunichinoMac-mini .ssh % vi config 
mor@JunichinoMac-mini .ssh % cat config
Host bitbucket.org
    UseKeychain yes
    AddKeysToAgent yes
    IdentityFile ~/.ssh/bitbucket.openssh.private
mor@JunichinoMac-mini .ssh % 

UseKeychain yes がキーチェーンを使う(プライベートキーのパスワードをキーチェーンから取得する)ということであり、AddKeysToAgent が ssh-agent の起動のたびにプライベートキーを IdentityFile から取得する、という設定になります。

これで実行できるか一度ログアウトして試してみると、問題なく、プルなどができました!

なお、 .ssh/config の書き方は、下記記事などを参考にしました。

Using the SSH Config File | Linuxize

参考1:毎回プライベートキーを入力する方法(失敗)

なお、 ~/.ssh/config の UseKeychain を no にして、毎回プライベートキーのパスワードを入力させようと思ったのですが、どうも SourceTree 側が対応していないようで、 passphrase 入力用のダイアログなどが表示されずに、単にエラーで終わってしまいます。

なので、当面は、Keychain に設定したプライベートキーのパスワードを利用する形で運用しようと思います。

参考2:プライベートキーの削除方法(失敗)

上記の一連の作業の結果、キーチェーンに、同じプライベートキーが2つのエントリーとして登録されてしまいました。キーチェーンアクセスで確認すると、

f:id:junichim:20201130154501p:plain

こんな感じで、2つのエントリーがあるのがわかります。ssh-add -K でパスワードファイルを指定する際のパス名違いですね。

なので、2つあるのも気持ち悪いので、これを削除する方法を調べたのですが、結局、わかりませんでした。

一応参考までに試した方法を書いておきます。

方法1

key chain の削除するには、プライベートキーに対応するパブリックキーが必要だそうです。

password - How do I remove an ssh private key from ssh-agent/keychain - Ask Different

まず、パブリックキーを生成します。

mor@JunichinoMac-mini .ssh % ssh-keygen -y -f ./bitbucket.openssh.private > bitbucket.openssh.public  
Enter passphrase: 
mor@JunichinoMac-mini .ssh % 

パブリックキーができたら、削除します。下記の記事などにあるように ssh-add -K -d のように2つのオプションを同時に指定する必要があるようです。

Stupid ssh-add Tricks - Stuff… And Things…

How To Stop macOS Sierra From Remembering Your SSH Key Passphrase - TeckLyfe

mor@JunichinoMac-mini ~ % ssh-add -K -d ~/.ssh/bitbucket.openssh.public 
Identity removed: /Users/mor/.ssh/bitbucket.openssh.public (/Users/mor/.ssh/bitbucket.openssh.public)
mor@JunichinoMac-mini ~ % 

これでうまくいっているように見えるのですが、キーチェーンアクセスから表示すると、キーチェーンが残ったままです。

もう少し細かく言うと、実は、 ssh-add -K で登録した直後なら、この方法でキーチェーンから削除できたのですが、一旦シャットダウンして、改めて過去に登録したプライベートキーのキーチェーンを削除しようとした場合は削除されませんでした。

結局、この理由がわからず、キーチェーンから削除ができませんでした。

方法2:『ローカル項目』を直接削除する

sshのプライベートキーは、キーチェーンの『ローカル項目』に入っていました。で、この『ローカル項目』は sqlite3 のデータベースファイルだそうです。 なので、このデータベースファイルから直接キーチェーンの該当項目を削除する方法が見つかりました。

How To Stop macOS Sierra From Remembering Your SSH Key Passphrase - TeckLyfe

rdar://28394826: macOS Sierra permanently remembers SSH key passphrase by default

試しに、当該ファイルのコピーを作って、確認してみると、

mor@JunichinoMac-mini tmp % cp -p ~/Library/Keychains/ハードウェアUUID/keychain-2.db .
mor@JunichinoMac-mini tmp % 
mor@JunichinoMac-mini tmp % sqlite3 keychain-2.db "select rowid, agrp from genp where agrp='com.apple.ssh.passphrases'"
71|com.apple.ssh.passphrases
92|com.apple.ssh.passphrases
mor@JunichinoMac-mini tmp % 

のように、当該レコードが存在しているようです。

ただ、この方法はちょっと怖いので、残念ながら、まだ試していません。

ということで、これについては、当面ペンディングです。

最後に

ということで、一応 SourceTree から Bitbucket へ SSH 経由でアクセスできるようになりました。 Mac ユーザーにとっては、当たり前なんでしょうが、なかなか慣れないシステムだと、前途多難です・・・