0

My RoR app needs to access a remote database (FWIW it's mysql hosted on rds.amazonaws.com). The only way to access it is through an SSH tunnel.

I've already tested access on my local machine. I'm setting up the tunnel via the equivalent of:

ssh -f -N -L 3307:longname.rds.amazonaws.com:3306 remote_user@remote_host.com 

(but see https://stackoverflow.com/a/27305457/558639 to see how I'm actually doing it). At any rate, I will need to install an SSH key pair (both private and public parts) on Heroku for this to work.

I'm on unfamiliar territory here, though. I could write a script that starts up at the beginning of a Heroku session that installs the keys. What's the right way to accomplish this and not expose the private key unnecessarily?

Community
  • 1
  • 1
fearless_fool
  • 33,645
  • 23
  • 135
  • 217

1 Answers1

0

Here's what I've come up with. (See SSH tunneling from Heroku for a longer description.)

  1. set up a bunch of environment variables, including the public and private keys, using heroku config:set NAME1=value1 NAME2=value2 etc...
  2. create .profile.d/web-setup.sh with the following contents. Note that as per https://devcenter.heroku.com/articles/profiled, any file in the .profile.d directory will be run when the dyno is first set up.

NOTE: This way, the private SSH key only appears as a configuration variable in the heroku environment. Since other sensitive information is kept there, I assume that this is a relatively safe approach.

The .profile.d/web-setup.sh file contains:

# file=.profile.d/web-setup.sh

# create keypair files on this dyno
echo $0: creating public and private key files
mkdir -p ${HOME}/.ssh
echo "${PUBLIC_KEY}" > ${HOME}/.ssh/heroku_id_rsa.pub
chmod 644 ${HOME}/.ssh/heroku_id_rsa.pub
# note the use of double quotes to preserve newlines!
echo "${PRIVATE_KEY}" > ${HOME}/.ssh/heroku_id_rsa
chmod 600 ${HOME}/.ssh/heroku_id_rsa

# You may need to preload known-hosts here.  See
# https://stackoverflow.com/questions/21575582/ssh-tunneling-from-heroku/27361295#27361295
# on how to do that.

# open a tunnel if not already running
SSH_CMD="ssh -f -i ${HOME}/.ssh/heroku_id_rsa -N -L ${LOCAL_PORT}:${REMOTE_MYSQL_HOST}:${MYSQL_PORT} ${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
Community
  • 1
  • 1
fearless_fool
  • 33,645
  • 23
  • 135
  • 217