Skip to content

Instantly share code, notes, and snippets.

@toonetown
Last active February 14, 2023 14:20
Show Gist options
  • Save toonetown/b45ccff51065cc33d982c10989c85590 to your computer and use it in GitHub Desktop.
Save toonetown/b45ccff51065cc33d982c10989c85590 to your computer and use it in GitHub Desktop.
Leverages ssh and openconnect to connect Shimo to PulseSecure hosts
#!/bin/bash
: ${NUM_FAILURES_ALLOWED:=10}
: ${SLEEP_PING_TIME:=10}
if [ "${1}" == "-c" -a -n "${2}" ]; then SHIMO_SCRIPT_CFG="${2}"; shift 2; fi
if [ -n "${SHIMO_SCRIPT_CFG}" ]; then
: ${SHIMO_HOME:="${HOME}/Library/Application Support/Shimo"}
: ${SHIMO_SCRIPT_HOME:="${SHIMO_HOME}/Scripts"}
: ${SHIMO_CONFIG_DIR:="${SHIMO_SCRIPT_HOME}/${SHIMO_SCRIPT_CFG}"}
: ${PULSE_VPN_CONF:="${SHIMO_CONFIG_DIR}/openconnect.conf"}
[ -f "${PULSE_VPN_CONF}" ] && export PULSE_VPN_CONF || echo "${PULSE_VPN_CONF} not found" >&2;
fi
if [ "${1}" == "env" ]; then
[[ $0 != "$BASH_SOURCE" ]] || { echo "Usage: source ${0} env [msg]" >&2; exit 1; }
[ -f "${HOME}/.bashrc" ] && source "${HOME}/.bashrc"
[ -n "${SHIMO_CONFIG_DIR}" ] || { echo "Requires SHIMO_CONFIG_DIR to be set" >&2; return 1; }
[[ ${SHIMO_CONFIG_DIR} != /* ]] && SHIMO_CONFIG_DIR="$(dirname "${0}")/${SHIMO_CONFIG_DIR}"
[ -d "${SHIMO_CONFIG_DIR}" ] || { echo "Configuration directory ${SHIMO_CONFIG_DIR} does not exist" >&2; return 1; }
: ${PULSE_VPN_CONF:="${SHIMO_CONFIG_DIR}/openconnect.conf"}
[ -f "${PULSE_VPN_CONF}" ] || { echo "${PULSE_VPN_CONF} not found" >&2; return 1; }
export PULSE_VPN_CONF
VPNC_SCRIPT="$(cat "${PULSE_VPN_CONF}" | grep '^script=' | cut -d'=' -f2 | sed -e 's/"//g')"
grep -q "env-only" "${VPNC_SCRIPT}" && source "${VPNC_SCRIPT}" env-only
[ -n "${SHIMO_ACCOUNT}" ] || { echo "Requires SHIMO_ACCOUNT to be set" >&2; return 1; }
SHIMO_INFO="$(sqlite3 "${HOME}/Library/Application Support/Shimo/Shimo4Profiles.sqlite" \
"select zusername, zremotehost from zbaseaccount where zaccountname='${SHIMO_ACCOUNT}';")"
[ -n "${SHIMO_INFO}" ] || { echo "Could not find info for '${SHIMO_ACCOUNT}'" >&2; return 1; }
export PULSE_KEYCHAIN_ITEM="Shimo: ${SHIMO_ACCOUNT}"
export PULSE_VPN_USER="$(echo "${SHIMO_INFO}" | cut -d'|' -f1)"
export PULSE_VPN_HOST="$(echo "${SHIMO_INFO}" | cut -d'|' -f2)"
[ -x "${SHIMO_CONFIG_DIR}/env" ] && source "${SHIMO_CONFIG_DIR}/env"
[ -n "${2}" ] && echo "${SHIMO_ACCOUNT} ${2}"
return 0
fi
if [ "$(id -u)" != "0" ]; then sudo "${0}" "$@"; exit $?; fi
if [ "${1}" == "setup" ]; then
[ -n "${PULSE_KEYCHAIN_ITEM}" ] || { echo "Requires PULSE_KEYCHAIN_ITEM to be set" >&2; exit 1; }
[ -f "${HOME}/.pulse-keychain" ] && { /usr/bin/security unlock-keychain -p "$(cat "${HOME}/.pulse-keychain")"; }
/usr/bin/security find-generic-password -s "${PULSE_KEYCHAIN_ITEM}" -w &>/dev/null && exit $?
/usr/bin/security delete-generic-password -s "TMP-${PULSE_KEYCHAIN_ITEM}" &>/dev/null
while [ -z "${_PW}" ]; do
_PW="$(osascript -e "set t to text returned of (display dialog \"Enter password for ${PULSE_KEYCHAIN_ITEM}\" \
with title \"${PULSE_KEYCHAIN_ITEM} Password\" \
default answer \"\" \
buttons {\"Cancel\", \"Continue\"} \
default button 2 \
hidden answer true)")" || exit $?
done
/usr/bin/security add-generic-password -a "TMP-${PULSE_KEYCHAIN_ITEM}" \
-s "TMP-${PULSE_KEYCHAIN_ITEM}" \
-w "${_PW}" &>/dev/null
exit $?
fi
case "${1}" in
"ssh-vpn")
NC_HOST="${2}"
NC_PORT="${3}"
[ -n "${NC_HOST}" -a -n "${NC_PORT}" ] || { echo "Usage: ${0} ssh-vpn <NC_HOST> <NC_PORT> [wait]" >&2; exit 1; }
"${0}" wait start "${4:-60}" &>/dev/null && /usr/bin/nc "${NC_HOST}" "${NC_PORT}"
;;
"start")
[ "$("${0}" status)" == "Stopped" ] || { echo "Already running" >&2; exit 1; }
[ -n "${PULSE_KEYCHAIN_ITEM}" ] || { echo "Requires PULSE_KEYCHAIN_ITEM to be set" >&2; exit 1; }
[ -n "${PULSE_VPN_CONF}" ] || { echo "Requires PULSE_VPN_CONF to be set" >&2; exit 1; }
[ -n "${PULSE_VPN_HOST}" ] || { echo "Requires PULSE_VPN_HOST to be set" >&2; exit 1; }
[ -n "${PULSE_VPN_USER}" ] || { echo "Requires PULSE_VPN_USER to be set" >&2; exit 1; }
PIDFILE_STARTING="$(cat "${PULSE_VPN_CONF}" | grep '^pid-file=' | cut -d'=' -f2).start"
echo "$$" > "${PIDFILE_STARTING}"
[ -f "${HOME}/.pulse-keychain" ] && { /usr/bin/security unlock-keychain -p "$(cat "${HOME}/.pulse-keychain")"; }
echo -n "$(
/usr/bin/security find-generic-password -s "${PULSE_KEYCHAIN_ITEM}" -w 2>/dev/null || \
/usr/bin/security find-generic-password -s "TMP-${PULSE_KEYCHAIN_ITEM}" -w 2>/dev/null \
)" \
| /usr/local/bin/openconnect --user="${PULSE_VPN_USER}" --passwd-on-stdin \
--config="${PULSE_VPN_CONF}" \
"${PULSE_VPN_HOST}" \
>>/var/log/shimo-pulse-vpnc-conn.log \
2>>/var/log/shimo-pulse-vpnc-conn.err || {
rm -f "${PIDFILE_STARTING}"
exit 1
}
rm -f "${PIDFILE_STARTING}"
;;
"stop")
[ "$("${0}" status)" == "Starting" ] && {
PIDFILE_STARTING="$(cat "${PULSE_VPN_CONF}" | grep '^pid-file=' | cut -d'=' -f2).start"
rm -rf "${PIDFILE_STARTING}"
exit 0
}
[ "$("${0}" status)" == "Running" ] || { echo "Already stopped" >&2; exit 1; }
[ -n "${PULSE_VPN_CONF}" ] || { echo "Requires PULSE_VPN_CONF to be set" >&2; exit 1; }
PIDFILE="$(cat "${PULSE_VPN_CONF}" | grep '^pid-file=' | cut -d'=' -f2)"
kill -SIGINT $(cat "${PIDFILE}")
;;
"reconnect")
[ "$("${0}" status)" == "Running" ] || { echo "Not running" >&2; exit 1; }
[ -n "${PULSE_VPN_CONF}" ] || { echo "Requires PULSE_VPN_CONF to be set" >&2; exit 1; }
PIDFILE="$(cat "${PULSE_VPN_CONF}" | grep '^pid-file=' | cut -d'=' -f2)"
kill -SIGUSR2 $(cat "${PIDFILE}")
;;
"restart")
"${0}" stop &>/dev/null; "${0}" start || exit $?
;;
"status")
[ -n "${PULSE_VPN_CONF}" ] || { echo "Requires PULSE_VPN_CONF to be set" >&2; exit 1; }
PIDFILE="$(cat "${PULSE_VPN_CONF}" | grep '^pid-file=' | cut -d'=' -f2)"
PIDFILE_STARTING="$(cat "${PULSE_VPN_CONF}" | grep '^pid-file=' | cut -d'=' -f2).start"
[ -d "$(dirname "${PIDFILE}")" ] || mkdir -p "$(dirname "${PIDFILE}")"
[ -f "${PIDFILE}" ] && {
rm -f "${PIDFILE_STARTING}"; echo "Running"
} || {
[ -f "${PIDFILE_STARTING}" ] && echo "Starting" || echo "Stopped"
}
;;
"wait")
[ -n "${PULSE_VPN_CONF}" ] || { echo "Requires PULSE_VPN_CONF to be set" >&2; exit 1; }
x=0; t=${3:-10}0; s=0
case "${2}" in
"start")
while [ "$("${0}" status)" != "Running" -a ${x} -lt ${t} ]; do
[ "$("${0}" status)" == "Stopped" -a ${s} -eq 1 ] && { echo "Cancelled"; exit 1; }
[ "$("${0}" status)" == "Starting" ] && s=1
x=$((x+1)); sleep .1
done
;;
"stop") while [ "$("${0}" status)" != "Stopped" -a ${x} -lt ${t} ]; do x=$((x+1)); sleep .1; done ;;
*) echo "Invalid wait action '${2}'. Choose one of 'start', or 'stop'"; exit 1 ;;
esac
[ ${x} -lt ${t} ] && exit 0 || { echo "Timed out"; exit 1; }
;;
*)
echo "Invalid action '${1}'. Choose one of 'start', 'stop', 'reconnect', 'restart', 'status', 'setup' 'env'"
exit 1
;;
esac
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment