Make installer interactive for credential source selection
This commit is contained in:
@@ -7,6 +7,7 @@ CONFIG_FILE="$CONFIG_DIR/env"
|
||||
_ENV_LEMANA_VPN_USERNAME="${LEMANA_VPN_USERNAME+x}${LEMANA_VPN_USERNAME-}"
|
||||
_ENV_LEMANA_VPN_BW_ITEM="${LEMANA_VPN_BW_ITEM+x}${LEMANA_VPN_BW_ITEM-}"
|
||||
_ENV_LEMANA_VPN_USE_BITWARDEN="${LEMANA_VPN_USE_BITWARDEN+x}${LEMANA_VPN_USE_BITWARDEN-}"
|
||||
_ENV_LEMANA_VPN_CREDENTIAL_SOURCE="${LEMANA_VPN_CREDENTIAL_SOURCE+x}${LEMANA_VPN_CREDENTIAL_SOURCE-}"
|
||||
_ENV_LEMANA_VPN_USE_TOUCHID="${LEMANA_VPN_USE_TOUCHID+x}${LEMANA_VPN_USE_TOUCHID-}"
|
||||
_ENV_LEMANA_VPN_DNS_CLEANUP="${LEMANA_VPN_DNS_CLEANUP+x}${LEMANA_VPN_DNS_CLEANUP-}"
|
||||
|
||||
@@ -18,6 +19,7 @@ fi
|
||||
[[ "${_ENV_LEMANA_VPN_USERNAME:0:1}" == "x" ]] && LEMANA_VPN_USERNAME="${_ENV_LEMANA_VPN_USERNAME:1}"
|
||||
[[ "${_ENV_LEMANA_VPN_BW_ITEM:0:1}" == "x" ]] && LEMANA_VPN_BW_ITEM="${_ENV_LEMANA_VPN_BW_ITEM:1}"
|
||||
[[ "${_ENV_LEMANA_VPN_USE_BITWARDEN:0:1}" == "x" ]] && LEMANA_VPN_USE_BITWARDEN="${_ENV_LEMANA_VPN_USE_BITWARDEN:1}"
|
||||
[[ "${_ENV_LEMANA_VPN_CREDENTIAL_SOURCE:0:1}" == "x" ]] && LEMANA_VPN_CREDENTIAL_SOURCE="${_ENV_LEMANA_VPN_CREDENTIAL_SOURCE:1}"
|
||||
[[ "${_ENV_LEMANA_VPN_USE_TOUCHID:0:1}" == "x" ]] && LEMANA_VPN_USE_TOUCHID="${_ENV_LEMANA_VPN_USE_TOUCHID:1}"
|
||||
[[ "${_ENV_LEMANA_VPN_DNS_CLEANUP:0:1}" == "x" ]] && LEMANA_VPN_DNS_CLEANUP="${_ENV_LEMANA_VPN_DNS_CLEANUP:1}"
|
||||
|
||||
@@ -27,8 +29,32 @@ OC_BIN="${LEMANA_VPN_OC_BIN:-$HOME/.local/bin/openconnect-lite}"
|
||||
BW_ITEM_NAME="${LEMANA_VPN_BW_ITEM:-LM LDAP}"
|
||||
KC_USERNAME="${LEMANA_VPN_USERNAME:-60103293}"
|
||||
KC_FP="${LEMANA_VPN_KEYCHAIN_FINGERPRINT:-$HOME/bin/keychain-fingerprint}"
|
||||
USE_BITWARDEN="${LEMANA_VPN_USE_BITWARDEN:-1}"
|
||||
CREDENTIAL_SOURCE="${LEMANA_VPN_CREDENTIAL_SOURCE:-}"
|
||||
if [[ -z "$CREDENTIAL_SOURCE" ]]; then
|
||||
if [[ "${LEMANA_VPN_USE_BITWARDEN:-1}" == "1" ]]; then
|
||||
CREDENTIAL_SOURCE="bitwarden"
|
||||
else
|
||||
CREDENTIAL_SOURCE="keychain"
|
||||
fi
|
||||
fi
|
||||
|
||||
case "$CREDENTIAL_SOURCE" in
|
||||
bitwarden|keychain) ;;
|
||||
*)
|
||||
printf 'Unknown credential source: %s. Use bitwarden or keychain.\n' "$CREDENTIAL_SOURCE" >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
|
||||
if [[ "$CREDENTIAL_SOURCE" == "bitwarden" ]]; then
|
||||
USE_BITWARDEN="1"
|
||||
else
|
||||
USE_BITWARDEN="0"
|
||||
fi
|
||||
USE_TOUCHID="${LEMANA_VPN_USE_TOUCHID:-1}"
|
||||
if [[ "$CREDENTIAL_SOURCE" == "keychain" ]]; then
|
||||
USE_TOUCHID="0"
|
||||
fi
|
||||
CACHE_BW_SESSION="${LEMANA_VPN_CACHE_BW_SESSION:-0}"
|
||||
DNS_CLEANUP="${LEMANA_VPN_DNS_CLEANUP:-/usr/local/sbin/lemana-vpn-dns-cleanup}"
|
||||
APP_DIR="${LEMANA_VPN_APP_DIR:-$HOME/Applications/LemanaVPN.app}"
|
||||
@@ -70,7 +96,7 @@ Usage: vpn-lemanapro.sh [--auto|--manual] [--debug] [--json] [--status] [--confi
|
||||
--manual-sso Compatibility alias for --manual
|
||||
--debug Passthrough debug logs; also shows browser in auto mode
|
||||
--json Emit JSON Lines events for UI wrappers
|
||||
--configure-keychain Prompt for LDAP password and TOTP secret, then save them to Keychain
|
||||
--configure-keychain Configure the keychain credential source: LDAP password plus permanent TOTP seed or otpauth:// URI
|
||||
--patch-only Apply openconnect-lite runtime patches and exit
|
||||
HELP
|
||||
exit 0
|
||||
@@ -196,6 +222,7 @@ _module_status_json() {
|
||||
local openconnect_installed openconnect_lite_installed bitwarden_installed touchid_installed dns_cleanup_installed
|
||||
local app_installed app_autostart
|
||||
local config_present oc_config_present patch_backup_present patches_active keychain_password keychain_totp_seed
|
||||
local credential_keychain_ready
|
||||
openconnect_installed="$(_module_bool command -v openconnect)"
|
||||
openconnect_lite_installed="$(_module_bool test -x "$OC_BIN")"
|
||||
bitwarden_installed="$(_module_bool command -v bw)"
|
||||
@@ -209,12 +236,15 @@ _module_status_json() {
|
||||
patches_active="$(_module_bool _patches_active)"
|
||||
keychain_password="$(_module_bool _keychain_has openconnect-lite "$KC_USERNAME")"
|
||||
keychain_totp_seed="$(_module_bool _keychain_has openconnect-lite "totp/$KC_USERNAME")"
|
||||
credential_keychain_ready="$([[ "$keychain_password" == "true" && "$keychain_totp_seed" == "true" ]] && printf true || printf false)"
|
||||
|
||||
printf '{"core":{"openconnect":%s,"openconnect_lite":%s,"config":%s,"openconnect_lite_config":%s},"bitwarden":{"enabled":%s,"installed":%s,"item":"%s"},"touchid":{"enabled":%s,"installed":%s},"keychain":{"password":%s,"totp_seed":%s},"dns_cleanup":{"installed":%s},"patches":{"active":%s,"backup":%s},"app":{"installed":%s,"autostart":%s}}' \
|
||||
printf '{"core":{"openconnect":%s,"openconnect_lite":%s,"config":%s,"openconnect_lite_config":%s},"credentials":{"source":"%s","keychain_ready":%s},"bitwarden":{"enabled":%s,"installed":%s,"item":"%s"},"touchid":{"enabled":%s,"installed":%s},"keychain":{"password":%s,"totp_seed":%s},"dns_cleanup":{"installed":%s},"patches":{"active":%s,"backup":%s},"app":{"installed":%s,"autostart":%s}}' \
|
||||
"$openconnect_installed" \
|
||||
"$openconnect_lite_installed" \
|
||||
"$config_present" \
|
||||
"$oc_config_present" \
|
||||
"$CREDENTIAL_SOURCE" \
|
||||
"$credential_keychain_ready" \
|
||||
"$([[ "$USE_BITWARDEN" == "1" ]] && printf true || printf false)" \
|
||||
"$bitwarden_installed" \
|
||||
"$BW_ITEM_NAME" \
|
||||
@@ -258,7 +288,7 @@ _module_status_human() {
|
||||
app_installed="$(_module_bool test -x "$APP_DIR/Contents/MacOS/LemanaVPN")"
|
||||
app_autostart="$(_module_bool test -f "$LAUNCH_AGENT")"
|
||||
|
||||
printf 'Modules: %s %s, ' "$([[ "$core" == "core=ok" ]] && printf '✅' || printf '⚠️')" "$core"
|
||||
printf 'Modules: %s %s, 🔐 credential_source=%s, ' "$([[ "$core" == "core=ok" ]] && printf '✅' || printf '⚠️')" "$core" "$CREDENTIAL_SOURCE"
|
||||
_module_human_part "bitwarden" "$USE_BITWARDEN" "$bitwarden_installed"
|
||||
printf ', '
|
||||
_module_human_part "touchid" "$USE_TOUCHID" "$touchid_installed"
|
||||
@@ -586,6 +616,34 @@ if totp_secret:
|
||||
PY
|
||||
}
|
||||
|
||||
_normalize_totp_secret() {
|
||||
_VPN_TOTP_INPUT="$1" python3 - <<'PY'
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import urllib.parse
|
||||
|
||||
value = os.environ.get("_VPN_TOTP_INPUT", "").strip()
|
||||
|
||||
if value.lower().startswith("otpauth://"):
|
||||
parsed = urllib.parse.urlparse(value)
|
||||
query = urllib.parse.parse_qs(parsed.query)
|
||||
value = query.get("secret", [""])[0]
|
||||
|
||||
value = re.sub(r"[\s-]+", "", value).upper()
|
||||
|
||||
if not value:
|
||||
print("", end="")
|
||||
sys.exit(0)
|
||||
|
||||
if not re.fullmatch(r"[A-Z2-7]+=*", value):
|
||||
print("Invalid TOTP seed. Use a BASE32 secret or an otpauth:// URI with secret=BASE32.", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
print(value)
|
||||
PY
|
||||
}
|
||||
|
||||
_can_prompt() {
|
||||
[[ -t 0 ]]
|
||||
}
|
||||
@@ -624,6 +682,10 @@ _configure_keychain() {
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [[ -n "$totp_secret" ]]; then
|
||||
totp_secret="$(_normalize_totp_secret "$totp_secret")"
|
||||
fi
|
||||
|
||||
_store_keychain "$password" "$totp_secret"
|
||||
printf 'Credentials are ready in macOS Keychain for openconnect-lite/%s.\n' "$KC_USERNAME"
|
||||
}
|
||||
@@ -634,18 +696,18 @@ _ensure_keychain_credentials() {
|
||||
_keychain_has openconnect-lite "totp/$KC_USERNAME" && totp_present=true
|
||||
|
||||
if [[ "$password_present" == "true" && "$totp_present" == "true" ]]; then
|
||||
if [[ "$USE_BITWARDEN" == "1" ]]; then
|
||||
_emit '{"event":"keychain_ready","source":"keychain"}' "LDAP credentials are ready in macOS Keychain for $KC_USERNAME."
|
||||
if [[ "$CREDENTIAL_SOURCE" == "bitwarden" ]]; then
|
||||
_emit '{"event":"keychain_ready","source":"bitwarden"}' "Bitwarden source synced LDAP credentials into macOS Keychain for $KC_USERNAME."
|
||||
else
|
||||
_emit '{"event":"keychain_ready","source":"keychain","bitwarden":false}' "Bitwarden is disabled. Using saved LDAP password and TOTP seed from macOS Keychain for $KC_USERNAME."
|
||||
_emit '{"event":"keychain_ready","source":"keychain"}' "Keychain source is ready: saved LDAP password and TOTP seed are available for $KC_USERNAME."
|
||||
fi
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ "$USE_BITWARDEN" == "1" ]]; then
|
||||
_emit '{"event":"keychain_required","bitwarden":true}' "Bitwarden sync did not produce complete Keychain credentials."
|
||||
if [[ "$CREDENTIAL_SOURCE" == "bitwarden" ]]; then
|
||||
_emit '{"event":"keychain_required","source":"bitwarden"}' "Bitwarden source did not produce complete Keychain credentials."
|
||||
else
|
||||
_emit '{"event":"keychain_required","bitwarden":false}' "Bitwarden is disabled and saved LDAP credentials are incomplete."
|
||||
_emit '{"event":"keychain_required","source":"keychain"}' "Keychain source is selected and saved LDAP credentials are incomplete."
|
||||
fi
|
||||
|
||||
if ! _can_prompt; then
|
||||
@@ -759,6 +821,9 @@ except Exception:
|
||||
')"
|
||||
|
||||
if [[ -n "$bw_password" ]]; then
|
||||
if [[ -n "$bw_totp_secret" ]]; then
|
||||
bw_totp_secret="$(_normalize_totp_secret "$bw_totp_secret")"
|
||||
fi
|
||||
_store_keychain "$bw_password" "$bw_totp_secret"
|
||||
_emit '{"event":"bw_synced"}' "Credentials synced from Bitwarden to Keychain"
|
||||
else
|
||||
@@ -766,6 +831,17 @@ except Exception:
|
||||
fi
|
||||
}
|
||||
|
||||
_sync_credentials() {
|
||||
case "$CREDENTIAL_SOURCE" in
|
||||
bitwarden)
|
||||
_sync_bitwarden
|
||||
;;
|
||||
keychain)
|
||||
_emit '{"event":"credential_source","source":"keychain"}' "Credential source: macOS Keychain"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
_dns_cleanup() {
|
||||
_emit '{"event":"dns_cleanup"}' "Cleaning up VPN DNS..."
|
||||
if [[ -x "$DNS_CLEANUP" ]]; then
|
||||
@@ -857,7 +933,7 @@ else
|
||||
printf '{"event":"modules","modules":%s}\n' "$(_module_status_json)"
|
||||
fi
|
||||
|
||||
_sync_bitwarden
|
||||
_sync_credentials
|
||||
_ensure_keychain_credentials
|
||||
_patch_oc
|
||||
|
||||
|
||||
Reference in New Issue
Block a user