feca-mailshots-plugin/scripts/mysql_tunnel.sh

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