306 lines
9.2 KiB
Bash
Executable File
306 lines
9.2 KiB
Bash
Executable File
#!/bin/sh
|
||
set -eu
|
||
|
||
INSTALL_BIN_DIR="${LEMANA_VPN_BIN_DIR:-$HOME/bin}"
|
||
CONFIG_DIR="${LEMANA_VPN_CONFIG_DIR:-$HOME/.config/lemana-vpn}"
|
||
OC_CONFIG_DIR="${OPENCONNECT_LITE_CONFIG_DIR:-$HOME/.config/openconnect-lite}"
|
||
OC_VENV="${LEMANA_VPN_OC_VENV:-$HOME/.local/pipx/venvs/openconnect-lite}"
|
||
DNS_CLEANUP="${LEMANA_VPN_DNS_CLEANUP:-/usr/local/sbin/lemana-vpn-dns-cleanup}"
|
||
USERNAME="${LEMANA_VPN_USERNAME:-60103293}"
|
||
APP_DIR="${LEMANA_VPN_APP_DIR:-$HOME/Applications/LemanaVPN.app}"
|
||
LAUNCH_AGENT="$HOME/Library/LaunchAgents/ru.dokops.LemanaVPN.plist"
|
||
DRY_RUN=0
|
||
KEEP_CONFIG=0
|
||
KEEP_APP=0
|
||
REMOVE_KEYCHAIN=0
|
||
REMOVE_TOUCHID_HELPER=0
|
||
REMOVE_OPENCONNECT_LITE=0
|
||
|
||
if [ -t 1 ] && [ -z "${NO_COLOR:-}" ] && [ "${TERM:-}" != "dumb" ]; then
|
||
C_RESET="$(printf '\033[0m')"
|
||
C_BOLD="$(printf '\033[1m')"
|
||
C_DIM="$(printf '\033[2m')"
|
||
C_RED="$(printf '\033[31m')"
|
||
C_GREEN="$(printf '\033[32m')"
|
||
C_YELLOW="$(printf '\033[33m')"
|
||
C_BLUE="$(printf '\033[34m')"
|
||
C_CYAN="$(printf '\033[36m')"
|
||
else
|
||
C_RESET=""
|
||
C_BOLD=""
|
||
C_DIM=""
|
||
C_RED=""
|
||
C_GREEN=""
|
||
C_YELLOW=""
|
||
C_BLUE=""
|
||
C_CYAN=""
|
||
fi
|
||
|
||
if [ "${LEMANA_VPN_NO_EMOJI:-0}" = "1" ]; then
|
||
E_STEP=">"
|
||
E_INFO="i"
|
||
E_OK="+"
|
||
E_WARN="!"
|
||
E_SKIP="-"
|
||
E_ERROR="x"
|
||
else
|
||
E_STEP="➡️"
|
||
E_INFO="ℹ️"
|
||
E_OK="✅"
|
||
E_WARN="⚠️"
|
||
E_SKIP="⏭️"
|
||
E_ERROR="❌"
|
||
fi
|
||
|
||
usage() {
|
||
cat <<'USAGE'
|
||
Usage:
|
||
sh uninstall.sh [options]
|
||
|
||
Options:
|
||
--keep-config Keep ~/.config/lemana-vpn
|
||
--keep-app Keep ~/Applications/LemanaVPN.app and LaunchAgent
|
||
--remove-keychain Remove VPN-related Keychain entries
|
||
--remove-touchid-helper Remove ~/bin/keychain-fingerprint
|
||
--remove-openconnect-lite Remove pipx openconnect-lite after patch rollback
|
||
--dry-run Print actions without changing files
|
||
-h, --help Show this help
|
||
|
||
Default uninstall restores openconnect-lite patch backup, removes Lemana VPN
|
||
scripts/config/sudoers/zsh aliases, and keeps shared package dependencies.
|
||
USAGE
|
||
}
|
||
|
||
while [ "$#" -gt 0 ]; do
|
||
case "$1" in
|
||
--keep-config) KEEP_CONFIG=1 ;;
|
||
--keep-app) KEEP_APP=1 ;;
|
||
--remove-keychain) REMOVE_KEYCHAIN=1 ;;
|
||
--remove-touchid-helper) REMOVE_TOUCHID_HELPER=1 ;;
|
||
--remove-openconnect-lite) REMOVE_OPENCONNECT_LITE=1 ;;
|
||
--dry-run) DRY_RUN=1 ;;
|
||
-h|--help)
|
||
usage
|
||
exit 0
|
||
;;
|
||
*)
|
||
echo "Unknown option: $1" >&2
|
||
usage >&2
|
||
exit 1
|
||
;;
|
||
esac
|
||
shift
|
||
done
|
||
|
||
log() {
|
||
printf '%s\n' "$*"
|
||
}
|
||
|
||
color_line() {
|
||
color="$1"
|
||
shift
|
||
printf '%s%s%s\n' "$color" "$*" "$C_RESET"
|
||
}
|
||
|
||
log_step() {
|
||
color_line "$C_BOLD$C_CYAN" "$E_STEP $*"
|
||
}
|
||
|
||
log_info() {
|
||
color_line "$C_BLUE" "$E_INFO $*"
|
||
}
|
||
|
||
log_detail() {
|
||
color_line "$C_DIM" " $*"
|
||
}
|
||
|
||
log_ok() {
|
||
color_line "$C_GREEN" "$E_OK $*"
|
||
}
|
||
|
||
log_warn() {
|
||
color_line "$C_YELLOW" "$E_WARN $*"
|
||
}
|
||
|
||
log_skip() {
|
||
color_line "$C_DIM" "$E_SKIP $*"
|
||
}
|
||
|
||
die() {
|
||
printf '%s%s ERROR: %s%s\n' "$C_RED" "$E_ERROR" "$*" "$C_RESET" >&2
|
||
exit 1
|
||
}
|
||
|
||
run() {
|
||
if [ "$DRY_RUN" -eq 1 ]; then
|
||
printf '+'
|
||
for arg in "$@"; do
|
||
printf ' %s' "$arg"
|
||
done
|
||
printf '\n'
|
||
return 0
|
||
fi
|
||
"$@"
|
||
}
|
||
|
||
find_webengine_process() {
|
||
if [ -n "${LEMANA_VPN_WEBENGINE_PROCESS:-}" ]; then
|
||
printf '%s\n' "$LEMANA_VPN_WEBENGINE_PROCESS"
|
||
return 0
|
||
fi
|
||
find "$OC_VENV/lib" -path '*/site-packages/openconnect_lite/browser/webengine_process.py' -print -quit 2>/dev/null || true
|
||
}
|
||
|
||
restore_openconnect_lite_patch() {
|
||
backup="$CONFIG_DIR/patch-backups/webengine_process.py.before-lemana-vpn"
|
||
wep="$(find_webengine_process)"
|
||
|
||
log_step "Проверяю runtime-патчи openconnect-lite"
|
||
log_detail "Если Lemana VPN менял webengine_process.py, перед удалением возвращаем исходник из backup."
|
||
|
||
if [ ! -f "$backup" ]; then
|
||
log_skip "No openconnect-lite patch backup found; patch rollback skipped."
|
||
return 0
|
||
fi
|
||
|
||
if [ -z "$wep" ] || [ ! -f "$wep" ]; then
|
||
log_warn "openconnect-lite source not found; patch rollback skipped."
|
||
return 0
|
||
fi
|
||
|
||
log_info "Restoring openconnect-lite source from patch backup"
|
||
run cp "$backup" "$wep"
|
||
log_ok "openconnect-lite patch rollback completed"
|
||
}
|
||
|
||
remove_zshrc_block() {
|
||
zshrc="$HOME/.zshrc"
|
||
if [ ! -f "$zshrc" ]; then
|
||
log_skip "~/.zshrc not found; shell aliases skipped."
|
||
return 0
|
||
fi
|
||
|
||
tmp="$(mktemp)"
|
||
if [ "$DRY_RUN" -eq 1 ]; then
|
||
printf '+ update %s aliases\n' "$zshrc"
|
||
rm -f "$tmp"
|
||
return 0
|
||
fi
|
||
|
||
awk '
|
||
/^# >>> lemana-vpn$/ { skip=1; next }
|
||
/^# <<< lemana-vpn$/ { skip=0; next }
|
||
skip != 1 { print }
|
||
' "$zshrc" > "$tmp"
|
||
mv "$tmp" "$zshrc"
|
||
log_ok "Shell aliases removed from $zshrc"
|
||
}
|
||
|
||
remove_keychain_entries() {
|
||
if [ "$REMOVE_KEYCHAIN" -ne 1 ]; then
|
||
log_skip "Keychain cleanup disabled; LDAP/TOTP and Bitwarden cached entries are kept."
|
||
return 0
|
||
fi
|
||
|
||
log_step "Удаляю VPN-записи из macOS Keychain"
|
||
log_detail "Удаляются только записи openconnect-lite для пользователя $USERNAME и кэш Bitwarden Lemana VPN."
|
||
if [ "$DRY_RUN" -eq 1 ]; then
|
||
run security delete-generic-password -s openconnect-lite -a "$USERNAME"
|
||
run security delete-generic-password -s openconnect-lite -a "totp/$USERNAME"
|
||
run security delete-generic-password -s vpn-lemanapro -a bw-session
|
||
run security delete-generic-password -s vpn-lemanapro -a bw-master
|
||
else
|
||
security delete-generic-password -s openconnect-lite -a "$USERNAME" >/dev/null 2>&1 || true
|
||
security delete-generic-password -s openconnect-lite -a "totp/$USERNAME" >/dev/null 2>&1 || true
|
||
security delete-generic-password -s vpn-lemanapro -a bw-session >/dev/null 2>&1 || true
|
||
security delete-generic-password -s vpn-lemanapro -a bw-master >/dev/null 2>&1 || true
|
||
fi
|
||
log_ok "Keychain cleanup completed"
|
||
}
|
||
|
||
main() {
|
||
[ "$(uname -s)" = "Darwin" ] || die "This uninstaller supports macOS only"
|
||
|
||
log_step "Начинаю удаление Lemana VPN"
|
||
log_detail "По умолчанию удаляются скрипты, sudoers, DNS wrapper, config, aliases и приложение."
|
||
log_detail "Shared-зависимости Homebrew не удаляются; openconnect-lite удаляется только с --remove-openconnect-lite."
|
||
|
||
restore_openconnect_lite_patch
|
||
|
||
log_step "Удаляю CLI-скрипты"
|
||
log_detail "Убираю vpn-lemanapro.sh и локальный uninstall helper из $INSTALL_BIN_DIR."
|
||
run rm -f "$INSTALL_BIN_DIR/vpn-lemanapro.sh"
|
||
run rm -f "$INSTALL_BIN_DIR/uninstall-lemana-vpn.sh"
|
||
log_ok "CLI scripts removed"
|
||
if [ "$REMOVE_TOUCHID_HELPER" -eq 1 ]; then
|
||
log_info "Removing Touch ID helper: $INSTALL_BIN_DIR/keychain-fingerprint"
|
||
run rm -f "$INSTALL_BIN_DIR/keychain-fingerprint"
|
||
else
|
||
log_skip "Touch ID helper kept; use --remove-touchid-helper to remove it."
|
||
fi
|
||
|
||
log_step "Удаляю sudoers и DNS cleanup wrapper"
|
||
log_detail "macOS может запросить sudo-пароль, потому что эти файлы принадлежат root."
|
||
run sudo rm -f /etc/sudoers.d/lemana-vpn-openconnect /etc/sudoers.d/lemana-vpn-dns
|
||
run sudo rm -f "$DNS_CLEANUP"
|
||
log_ok "sudoers and DNS cleanup wrapper removed"
|
||
|
||
if [ "$KEEP_APP" -eq 0 ]; then
|
||
log_step "Удаляю Menu Bar app"
|
||
log_detail "Сначала останавливаю уже запущенное LemanaVPN, затем отключаю LaunchAgent и удаляю $APP_DIR."
|
||
if [ "$DRY_RUN" -eq 0 ]; then
|
||
if pgrep -x LemanaVPN >/dev/null 2>&1; then
|
||
log_info "Stopping running LemanaVPN process"
|
||
killall LemanaVPN >/dev/null 2>&1 || true
|
||
sleep 1
|
||
fi
|
||
launchctl unload "$LAUNCH_AGENT" >/dev/null 2>&1 || true
|
||
else
|
||
printf '+ killall LemanaVPN # if running\n'
|
||
printf '+ launchctl unload %s\n' "$LAUNCH_AGENT"
|
||
fi
|
||
run rm -f "$LAUNCH_AGENT"
|
||
run rm -rf "$APP_DIR"
|
||
log_ok "Menu Bar app removed"
|
||
else
|
||
log_skip "Menu Bar app kept because --keep-app is set."
|
||
fi
|
||
|
||
log_step "Удаляю shell aliases"
|
||
log_detail "Из ~/.zshrc удаляется только блок между # >>> lemana-vpn и # <<< lemana-vpn."
|
||
remove_zshrc_block
|
||
|
||
log_step "Удаляю openconnect-lite config"
|
||
log_detail "Удаляется профиль SSO, который был создан установщиком Lemana VPN."
|
||
run rm -f "$OC_CONFIG_DIR/config.toml"
|
||
log_ok "openconnect-lite config removed"
|
||
|
||
if [ "$KEEP_CONFIG" -eq 0 ]; then
|
||
log_step "Удаляю Lemana VPN config"
|
||
log_detail "Удаляется $CONFIG_DIR, включая backup runtime-патчей после их отката."
|
||
run rm -rf "$CONFIG_DIR"
|
||
log_ok "Lemana VPN config removed"
|
||
else
|
||
log_skip "Lemana VPN config kept because --keep-config is set."
|
||
fi
|
||
|
||
remove_keychain_entries
|
||
|
||
if [ "$REMOVE_OPENCONNECT_LITE" -eq 1 ]; then
|
||
if command -v pipx >/dev/null 2>&1; then
|
||
log_step "Удаляю openconnect-lite из pipx"
|
||
log_detail "Это опционально: пакет может использоваться не только Lemana VPN."
|
||
run pipx uninstall openconnect-lite
|
||
log_ok "openconnect-lite removed from pipx"
|
||
else
|
||
log_warn "pipx not found; openconnect-lite package removal skipped."
|
||
fi
|
||
else
|
||
log_skip "openconnect-lite kept; use --remove-openconnect-lite to uninstall it from pipx."
|
||
fi
|
||
|
||
log_ok "Done."
|
||
}
|
||
|
||
main "$@"
|