Herokuでホストされているサービスを提供しています。これにより、ユーザーはデータベースを使用して自分のデータについてレポートできます。私の顧客はHerokuアプリをデータベースに接続する必要があります。それらのいくつかは明らかにインターネット上でデータを平文で通過させることを恐れています。
Herokuでアプリ(Play Framework/Java)からマシンにSSHトンネルを開くことは可能ですか?
注意:私は HerokuからリモートDBへのSSHトンネリング? を知っていますが、その質問では、組み込みのHeroku dbを使用することが可能でした。
ありがとう、エイドリアン
これでこのパスをたどりました:はい、それはis herokuから外部データベースへのSSHトンネルをセットアップすることが可能です。 [注:私の特定のアプリはRuby on Railsで記述されていますが、ここに記載されているソリューションはHerokuでホストされているすべての言語で機能するはずです。
Herokuでアプリを実行しています。アプリは、分析のためにデータを取得する外部のMySQLデータベース(AWSでホストされている)にアクセスする必要があります。 MySQLデータベースへのアクセスはsshキーで保護されています。つまり、パスワードでアクセスすることはできません。sshキーペアが必要です。 Herokuは各dynoを新しく開始するので、適切な資格情報を使用してSSHトンネルをセットアップするにはどうすればよいですか?
スクリプトファイルを作成します(ssh_setup.shなど)。 $ {HOME} /。profile.d/ssh_setup.shに置きます。 Herokuは$ {HOME} /。profile.d内のファイルに気づき、dynoを作成するときにそれを実行します。スクリプトファイルを使用して〜/ .ssh/id_rsaおよび〜/ .ssh/id_rsa.pubを設定し、トンネルモードでsshを起動します。
鍵ペアを作成し、〜/ .ssh/heroku_id_rsaおよび〜/ .ssh/heroku_id_rsa.pubに保存します。空のパスフレーズを使用します(そうでない場合、Heroku dynoは起動時にプロンプトを表示しようとします):
$ ssh-keygen -t rsa -C "[email protected]"
Generating public/private rsa key pair.
Enter file in which to save the key (/home/.ssh/id_rsa): /home/.ssh/heroku_id_rsa
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/.ssh/heroku_id_rsa.
Your public key has been saved in /home/.ssh/heroku_id_rsa.pub.
PUBLICキー(〜/ .ssh/heroku_id_rsa.pub)を外部DBの管理者に送信し、そのキーを使用してアクセスを要求します。その後、ローカルマシンのシェルウィンドウに次のように入力できます。
$ ssh -v -i ~/.ssh/heroku_id_rsa -N -L 3307:${REMOTE_MYSQL_Host}:3306 ${TUNNEL_USER}@${TUNNEL_SITE}
どこ
次のものを含むデバッグ出力の長い文字列が表示されます。
debug1: Authentication succeeded (publickey).
...
debug1: forking to background
debug1: Entering interactive session.
おめでとう。自分のマシンで外部データベースへのトンネリングを設定しました。 Herokuに同じことをするように説得するために...
〜/ .ssh/heroku_id_rsaおよび〜/ .ssh/heroku_id_rsa.pubの内容を、起動時にHeroku dynoの対応するディレクトリにコピーすることが目的ですが、実際には秘密鍵をスクリプトファイル。
代わりに、Hyokuの構成変数を使用します。これは、dynoの起動時にシェル環境変数を簡単に(かつ安全に)設定します。
$ heroku config:set HEROKU_PRIVATE_KEY=`cat ~/.ssh/heroku_rsa_id`
$ heroku config:set HEROKU_PUBLIC_KEY=`cat ~/.ssh/heroku_rsa_id.pub`
ここでは、機密性の高い他のいくつかの変数も設定します。
$ heroku config:set REMOTE_MYSQL_Host=<your value of REMOTE_MYSQL_Host from above>
$ heroku config:set TUNNEL_USER=<your value of TUNNEL_USER from above>
$ heroku config:set TUNNEL_SITE=<your value of TUNNEL_SITE from above>
プロジェクトのホームディレクトリに、.profile.dディレクトリを作成します。そのディレクトリで、以下を作成します。
# file: .profile.d/ssh-setup.sh
#!/bin/bash
echo $0: creating public and private key files
# Create the .ssh directory
mkdir -p ${HOME}/.ssh
chmod 700 ${HOME}/.ssh
# Create the public and private key files from the environment variables.
echo "${HEROKU_PUBLIC_KEY}" > ${HOME}/.ssh/heroku_id_rsa.pub
chmod 644 ${HOME}/.ssh/heroku_id_rsa.pub
# Note use of double quotes, required to preserve newlines
echo "${HEROKU_PRIVATE_KEY}" > ${HOME}/.ssh/heroku_id_rsa
chmod 600 ${HOME}/.ssh/heroku_id_rsa
# Preload the known_hosts file (see "version 2" below)
# Start the SSH tunnel if not already running
SSH_CMD="ssh -f -i ${HOME}/.ssh/heroku_id_rsa -N -L 3307:${REMOTE_MYSQL_Host}:3306 ${REMOTE_USER}@${REMOTE_SITE}"
PID=`pgrep -f "${SSH_CMD}"`
if [ $PID ] ; then
echo $0: tunnel already running on ${PID}
else
echo $0 launching tunnel
$SSH_CMD
fi
あなたはドリルを知っています...
$ git add .
$ git commit -m 'launching ssh when Heroku dyno starts up'
$ git Push heroku master
やってみて...
$ heroku run sh
次のようなものが表示される場合があります。
Running `sh` attached to terminal... up, run.1926
bash: creating public and private key files
bash: launching tunnel
The authenticity of Host 'example.com (11.22.33.44)' can't be established.
ECDSA key fingerprint is 1f:aa:bb:cc:dd:ee:ff:11:22:33:44:55:66:77:88:99.
Are you sure you want to continue connecting (yes/no)?
これは、dynoが続行するためにユーザー入力を必要とすることを意味するため、問題です。しかし、これを修正しようとしています。以下はやや醜いハックですが、動作します。 (誰かがより良い解決策を持っている場合は、コメントしてください!)
(上から続行)プロンプトにyes
と答え、スクリプトを最後まで実行させます。次に、known_hostsファイルの出力をキャプチャします。
heroku $ cat ~/.ssh/known_hosts
|1|longstringofstuff= ecdsa-sha2-nistp256 more stuff=
|1|morestuff= ecdsa-sha2-nistp256 yetmorestuff=
その出力をコピーして、「preload the known_hosts」コメントの下のssh-setup.shファイルに貼り付け、次のように編集します。
# Preload the known_hosts file (see "version 2" below)
echo '|1|longstringofstuff= ecdsa-sha2-nistp256 more stuff=
|1|morestuff= ecdsa-sha2-nistp256 yetmorestuff=' > ${HOME}/.ssh/known_hosts
# Start the SSH tunnel if not already running
... etc ...
あなたはドリルを知っています...
$ git add .
$ git commit -m 'preload known_hosts file to avoid Prompt'
$ git Push heroku master
やってみて。運が良ければ、次のようなものが表示されます。
$ heroku run sh
Running `sh` attached to terminal... up, run.1926
bash: creating public and private key files
bash: launching tunnel
トンネルが適切に設定されていない場合は、スクリプトファイルのSSHコマンドに-v(詳細)引数を追加してみてください。
SSH_CMD="ssh -v -f -i ${HOME}/.ssh/heroku_id_rsa -N -L ${LOCAL_PORT}:${REMOTE_MYSQL_Host}:${MYSQL_PORT} ${REMOTE_USER}@${REMOTE_SITE}"
git add ... git commit ... git Push
シーケンスを繰り返し、heroku run sh
を呼び出します。大量のデバッグ出力が出力されます。私の頭脳よりも多くの頭脳を持つシステム管理者の友人は、その出力をデコードして、問題がどこにあるかを教えてくれるはずです。
Railsを実行している場合は、Railsアプリ内でデータベースにアクセスする方法が必要です。そうですか?config/database.yml
ファイルに以下を追加します(適切な名前を変更します) :
mysql_legacy:
adapter: mysql2
database: mysql_legacy
username: <%= ENV['LEGACY_DB_USERNAME'] || 'root' %>
password: <%= ENV['LEGACY_DB_PASSWORD'] || '' %>
Host: 127.0.0.1
port: 3307
注意すべき重要な点は、ホストはローカルホスト(127.0.0.1)であり、ポート(3307)はスクリプトでsshに指定された-L引数と一致する必要があることです。
-L 3307:${REMOTE_MYSQL_Host}:3306
他の場所で言われていることにもかかわらず、Herokuからトンネルを介してリモートデータベースにアクセスできます。上記のレシピは多くの仮定を行っていますが、いくつかのカスタマイズにより、特定のニーズに対応するはずです。
さあ、寝ます。