JenkinsでのGitHub連携・SSH認証に関して
レンタルサーバにjenkinsをインストールし、仮想マシン等を利用し開発環境を構築しようとしています。
しかし、jenkinsから仮想マシンにsshでログインし、githubに対しgit pull
する段階でジョブが固まってしまいます。
環境・状況
開発用ノートPC
Debian GNU/LINUX 8.0
ゲスト仮想マシン(ノートPC内)
VM:VirtualBox 4.3.30
OS:CentOS6.6
mem:512MB
HDD:8.0GB
ホストオンリーアダプタ(ホストとの通信用)->eth1 192.168.56.10
NAT(インターネットに出る用)
作業ユーザ:vagrant
jenkinsサーバ(レンタルVPS・固定IP・root権限)
OS:CentOS6.6
mem:1GB
HDD:50GB
作業ユーザ:jenkins
補足
ホストPC及びゲスト仮想マシンは固定IPを持っていない為、jenkinsサーバとの接続はssh forwordを使用しトンネルを掘っています。このトンネルの通信は正常に確保できています。
jenkinsサーバとgithubの連携設定は行っており、連携確認ができています。(githubにプッシュした際にjenkinsのジョブが発動できる状態になっています)
jenkinsサーバからゲスト仮想マシンにjenkinsでのsshプラグインを介して正常にログインできています。
githubの鍵は、jenkinsサーバ、ゲスト仮想マシンともに別個に登録し秘密鍵を持たせています。
やりたいこと
ホストノートPCでコーディング・開発を行い、githubにpushしたタイミングでjenkinsを介して、ゲスト仮想マシンで自動的にgithubからpullしたい。
行ったjenkinsジョブの設定
- [ソースコード管理]等項目は適切に設定
- ビルド・トリガはgithubプラグインを入れ、「Build when a change is pushed to -GitHub」に設定
ビルド環境はsshプラグインを入れ、「リモートホストでシェルを実行」を選択。ゲスト仮想マシンには秘密鍵を使用し
vagrant@localhost:10022
としてログインできるように設定(ptyを有効にしています)設定したシェルスクリプト
cd /var/www/html/hoge
git pull
当初この状態でジョブを発動したところ、githubに入る為の秘密鍵のパスフレーズを入れられていないため、弾かれジョブは失敗しました。
jenkinsのコンソール出力
~~(一部省略)
~~
cd /var/www/html/force
git pull
Permission denied (publickey).
fatal: The remote end hung up unexpectedly
[SSH] exit-status: 1
Finished: FAILURE
ssh-agentの使用
そこでゲスト仮想マシンでssh-agentを立ち上げ、予めssh-addにて鍵・パスフレーズを登録し、再度ジョブを発動させたところ、弾かれはしないのですが、ジョブが固まってしまいます。(ぐるぐるマークがずっと動いている状態)
手動では成功する
開発用ノートPCからか、jenkinsサーバから(jenkinsサーバに開発用ノートPCからsshでjenkinsユーザとしてログインしてから)直接SSHでゲスト仮想マシンに入り、git pull
すると成功します。
自分の理解では
開発用ノートPC->github->jenkinsサーバ->ゲスト仮想マシン->github
といった順序で動いていき、最終的にゲスト仮想マシンの秘密鍵を使ってgithubにログインしようとしているものと思っています。
おそらく今回の問題は鍵のパスフレーズをどのように入れるのかに関することとおもいますが、経験が浅く解決出来ていません。
今回のような構成がおかしいというご意見があるかと思いますが、個人的に後々にもssh forwordを利用した開発環境の構築が必要になってきますので、できれば今環境内での解決をご教授できればと思います。
よろしくお願いします。
追記
web等で検索したところexpectというコマンドでパスフレーズを入力できることがわかりました。
早速expectでシェルスクリプトを作成したところ、パスフレーズの入力に成功し、pullが成功しました。
#!/usr/bin/expect
expect -c "
set timeout 5
spawn git pull
expect \"Enter passphrase for key '/home/vagrant/.ssh/id_rsa':\"
send \"パスフレーズ\n\"
interact
"
結果的にジョブが成功したことにはなりますが、expectではシェルスクリプトにパスフレーズを記載する必要があり、あまり好ましい状態では無いように思えます。
できればセキュリティ的にも納得の行く方法で行えたらと思っています。
引き続き、よろしくお願いします。