Files

99 lines
4.7 KiB
Python

#!/usr/bin/env python3
"""Persisted auth selection with fake dependencies and no live connection."""
import json
import os
from pathlib import Path
import subprocess
import tempfile
ROOT = Path(__file__).resolve().parents[1]
CLI = ROOT / "bin/vpn-lemanapro.sh"
with tempfile.TemporaryDirectory(prefix="lemana-auth-") as temporary:
home = Path(temporary)
config = home / "config"
config.mkdir()
saved = config / "env"
custom = 'LEMANA_VPN_USERNAME="fixture-user"\nLEMANA_VPN_BW_ITEM="Corporate & VPN"\nLEMANA_VPN_LOG_MAX_BYTES="4096"\nLEMANA_VPN_USE_TOUCHID="0"\n'
saved.write_text(custom + 'LEMANA_VPN_MODE="manual-keychain"\n')
fake = home / "fake"
fake.mkdir()
fake.joinpath("security").write_text('''#!/bin/sh
while [ "$#" -gt 0 ]; do
if [ "$1" = -w ]; then echo forbidden-secret-read >> "$HOME/side-effects"; exit 1; fi
if [ "$1" = -a ]; then shift; account="$1"; fi
shift
done
case "${TEST_CREDENTIALS:-all}:$account" in none:*|password:totp/*) exit 1 ;; *) exit 0 ;; esac
''')
for name in ("sudo", "openconnect", "bw"):
fake.joinpath(name).write_text('#!/bin/sh\necho unexpected-execution >> "$HOME/side-effects"\nexit 1\n')
for path in fake.iterdir():
path.chmod(0o755)
env = {key: value for key, value in os.environ.items() if not key.startswith(("LEMANA_VPN_", "OPENCONNECT_LITE_"))}
env.update(HOME=temporary, PATH=str(fake) + ":" + os.environ["PATH"],
LEMANA_VPN_CONFIG_DIR=str(config), OPENCONNECT_LITE_CONFIG_DIR=str(home / "sso"),
LEMANA_VPN_STATUS_DIR=str(home / "state"), LEMANA_VPN_OC_VENV=str(home / "no-venv"),
LEMANA_VPN_OC_BIN=str(fake / "openconnect"), LEMANA_VPN_APP_DIR=str(home / "no-app"),
LEMANA_VPN_DNS_CLEANUP=str(fake / "sudo"))
def run(*args, extra=None, success=True):
result = subprocess.run(["bash", str(CLI), *args], env=dict(env, **(extra or {})),
text=True, capture_output=True, timeout=10)
if success:
assert result.returncode == 0, result.stderr
else:
assert result.returncode != 0, result.stdout
return result
def status(extra=None):
return json.loads(run("--status", "--json", extra=extra).stdout)["modules"]
for choice, mode, source, preferred in (
("keychain", "keychain-auto", "keychain", "keychain"),
("manual", "manual-keychain", "keychain", "keychain"),
("bitwarden", "bitwarden-auto", "bitwarden", "bitwarden"),
("manual", "manual-keychain", "keychain", "bitwarden"),
("auto", "bitwarden-auto", "bitwarden", "bitwarden"),
("keychain", "keychain-auto", "keychain", "keychain"),
):
run("--set-auth=" + choice)
modules = status()
assert modules["mode"]["id"] == mode
assert modules["auth"]["source"] == source
assert modules["auth"]["auto_source"] == preferred
assert modules["auth"]["mode"] == ("manual" if mode == "manual-keychain" else "auto")
assert modules["auth"]["ready"]
assert custom.rstrip() in saved.read_text()
assert saved.stat().st_mode & 0o777 == 0o600
assert not list(config.glob(".auth-env-*"))
assert not (home / "side-effects").exists()
assert not (home / "state").exists()
print("PASS saved selection: manual/automatic sources, remembered auto source, settings preserved, no connection or secret reads")
before = saved.read_text()
run("--set-auth=invalid", success=False)
assert saved.read_text() == before
fake.joinpath("python3").write_text('#!/bin/sh\nexit 1\n')
fake.joinpath("python3").chmod(0o755)
run("--set-auth=manual", success=False)
assert saved.read_text() == before
fake.joinpath("python3").unlink()
print("PASS failed/invalid save leaves active settings unchanged")
for credentials, hint in (("none", "--configure-login"), ("password", "--import-yandex-key")):
modules = status({"TEST_CREDENTIALS": credentials})
assert not modules["auth"]["ready"] and hint in modules["auth"]["setup_hint"]
failure = run("--json", extra={"TEST_CREDENTIALS": credentials}, success=False)
assert hint in failure.stdout
assert not (home / "side-effects").exists() and not (home / "state").exists()
print("PASS incomplete local automatic setup blocks client launch with correct guidance")
saved.write_text(custom + 'LEMANA_VPN_MODE="manual-keychain"\nLEMANA_VPN_LOCAL_OTP="1"\n')
assert status()["mode"]["id"] == "keychain-auto"
manual = json.loads(run("--manual", "--status", "--json").stdout)["modules"]
assert manual["mode"]["id"] == "manual-keychain" and not manual["local_otp"]
print("PASS approved legacy-local migration and explicit manual override")
print("auth settings checks ok")