119 lines
3.2 KiB
Bash
Executable File
119 lines
3.2 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
|
|
resolve_repo_root() {
|
|
local candidate
|
|
for candidate in "${SCRIPT_DIR}/.." "${SCRIPT_DIR}/../.." "${PWD}"; do
|
|
if [[ -f "${candidate}/credentials/.env" ]]; then
|
|
(cd "${candidate}" && pwd)
|
|
return 0
|
|
fi
|
|
done
|
|
return 1
|
|
}
|
|
|
|
if ! REPO_ROOT="$(resolve_repo_root)"; then
|
|
echo "Error: could not locate repository root containing credentials/.env" >&2
|
|
exit 1
|
|
fi
|
|
|
|
ENV_FILE="${REPO_ROOT}/credentials/.env"
|
|
|
|
if [[ ! -f "${ENV_FILE}" ]]; then
|
|
echo "Error: credentials file not found: ${ENV_FILE}" >&2
|
|
exit 1
|
|
fi
|
|
|
|
load_env_value() {
|
|
local key="$1"
|
|
local line
|
|
line="$(grep -E "^${key}=" "${ENV_FILE}" | tail -n 1 || true)"
|
|
line="${line#*=}"
|
|
line="${line%\"}"
|
|
line="${line#\"}"
|
|
line="${line%\'}"
|
|
line="${line#\'}"
|
|
printf '%s' "${line}"
|
|
}
|
|
|
|
SSH_HOST="$(load_env_value REMOTE_SSH_HOST)"
|
|
SSH_PORT="$(load_env_value REMOTE_SSH_PORT)"
|
|
SSH_USER="$(load_env_value REMOTE_SSH_USER)"
|
|
SSH_KEY_RAW="$(load_env_value REMOTE_SSH_KEY)"
|
|
REMOTE_MYSQL_HOST="$(load_env_value REMOTE_MYSQL_HOST)"
|
|
REMOTE_MYSQL_PORT="$(load_env_value REMOTE_MYSQL_PORT)"
|
|
LOCAL_PORT="${LOCAL_PORT:-13306}"
|
|
|
|
if [[ -z "${SSH_HOST}" || -z "${SSH_USER}" || -z "${SSH_KEY_RAW}" ]]; then
|
|
echo "Error: missing REMOTE_SSH_* values in ${ENV_FILE}" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if [[ -z "${SSH_PORT}" ]]; then SSH_PORT=22; fi
|
|
if [[ -z "${REMOTE_MYSQL_HOST}" ]]; then REMOTE_MYSQL_HOST=127.0.0.1; fi
|
|
if [[ -z "${REMOTE_MYSQL_PORT}" ]]; then REMOTE_MYSQL_PORT=3306; fi
|
|
|
|
if [[ "${SSH_KEY_RAW}" = /* ]]; then
|
|
SSH_KEY_PATH="${SSH_KEY_RAW}"
|
|
else
|
|
SSH_KEY_PATH="${REPO_ROOT}/${SSH_KEY_RAW}"
|
|
fi
|
|
|
|
if [[ ! -f "${SSH_KEY_PATH}" ]]; then
|
|
echo "Error: SSH key not found: ${SSH_KEY_PATH}" >&2
|
|
exit 1
|
|
fi
|
|
|
|
CONTROL_SOCKET="/tmp/mailshot-mysql-tunnel-${LOCAL_PORT}.sock"
|
|
SSH_TARGET="${SSH_USER}@${SSH_HOST}"
|
|
|
|
start_tunnel() {
|
|
if ssh -S "${CONTROL_SOCKET}" -p "${SSH_PORT}" -O check "${SSH_TARGET}" >/dev/null 2>&1; then
|
|
echo "Tunnel already running on 127.0.0.1:${LOCAL_PORT}"
|
|
return 0
|
|
fi
|
|
|
|
ssh -f -N \
|
|
-M -S "${CONTROL_SOCKET}" \
|
|
-o BatchMode=yes \
|
|
-o ExitOnForwardFailure=yes \
|
|
-o StrictHostKeyChecking=accept-new \
|
|
-i "${SSH_KEY_PATH}" \
|
|
-p "${SSH_PORT}" \
|
|
-L "127.0.0.1:${LOCAL_PORT}:${REMOTE_MYSQL_HOST}:${REMOTE_MYSQL_PORT}" \
|
|
"${SSH_TARGET}"
|
|
|
|
echo "Tunnel started: 127.0.0.1:${LOCAL_PORT} -> ${REMOTE_MYSQL_HOST}:${REMOTE_MYSQL_PORT} via ${SSH_TARGET}:${SSH_PORT}"
|
|
echo "Use in DBeaver: host=127.0.0.1 port=${LOCAL_PORT}"
|
|
}
|
|
|
|
stop_tunnel() {
|
|
if ssh -S "${CONTROL_SOCKET}" -p "${SSH_PORT}" -O exit "${SSH_TARGET}" >/dev/null 2>&1; then
|
|
rm -f "${CONTROL_SOCKET}" || true
|
|
echo "Tunnel stopped for 127.0.0.1:${LOCAL_PORT}"
|
|
else
|
|
echo "No active tunnel found for 127.0.0.1:${LOCAL_PORT}"
|
|
fi
|
|
}
|
|
|
|
status_tunnel() {
|
|
if ssh -S "${CONTROL_SOCKET}" -p "${SSH_PORT}" -O check "${SSH_TARGET}" >/dev/null 2>&1; then
|
|
echo "Tunnel is running on 127.0.0.1:${LOCAL_PORT}"
|
|
else
|
|
echo "Tunnel is not running on 127.0.0.1:${LOCAL_PORT}"
|
|
fi
|
|
}
|
|
|
|
CMD="${1:-start}"
|
|
case "${CMD}" in
|
|
start) start_tunnel ;;
|
|
stop) stop_tunnel ;;
|
|
status) status_tunnel ;;
|
|
*)
|
|
echo "Usage: $(basename "$0") [start|stop|status]"
|
|
exit 1
|
|
;;
|
|
esac
|