Remove local gateway unlock gate

This commit is contained in:
HumbleTurtle
2026-05-10 07:54:34 -03:00
parent e7aed9ddf6
commit dd0af0f6a9
7 changed files with 248 additions and 149 deletions
+17 -17
View File
@@ -24,7 +24,7 @@ def assert_equal(actual, expected, message):
def run():
mod = load_module()
calls = {"preregister": [], "setup": [], "unlock": [], "tmux": []}
calls = {"preregister": [], "setup": [], "open": [], "tmux": []}
mod.AUTH = {}
mod.TOKEN = None
@@ -32,7 +32,7 @@ def run():
mod.vault_exists = lambda: False
mod.gateway_is_unlocked = lambda: False
mod.gateway_setup = lambda payload: calls["setup"].append(payload) or {"status": "configured"}
mod.gateway_unlock = lambda passphrase: calls["unlock"].append(passphrase) or {"status": "unlocked"}
mod.gateway_open_local = lambda passphrase=None: calls["open"].append(passphrase) or {"status": "local_available"}
mod.gateway_tmux_configure = lambda payload: calls["tmux"].append(payload) or {"status": "configured"}
mod.gateway_status = lambda: {"status": "ok"}
mod.gateway_log = lambda *args, **kwargs: None
@@ -83,19 +83,19 @@ def run():
assert_equal(invalid_cli["status"], "bootstrap_token_invalid", "cli invalid token fallback")
calls["preregister"].clear()
calls["unlock"].clear()
calls["open"].clear()
calls["tmux"].clear()
mod.gateway_service_preregister = preregister
mod.TOKEN = None
mod.vault_exists = lambda: True
mod.gateway_is_unlocked = lambda: False
def unlock_existing(passphrase):
calls["unlock"].append(passphrase)
def open_existing(passphrase=None):
calls["open"].append(passphrase)
mod.TOKEN = "np_existing_worker"
return {"status": "unlocked"}
return {"status": "local_available"}
mod.gateway_unlock = unlock_existing
mod.gateway_open_local = open_existing
preserved_mcp = mod.mcp_gateway_configure({
"bootstrap_token": "npb_existing",
"passphrase": "pw_existing",
@@ -109,31 +109,31 @@ def run():
assert_equal(preserved_mcp["status"], "configured", "mcp preserved gateway should skip preregister")
assert_equal(preserved_cli["status"], "configured", "cli preserved gateway should skip preregister")
assert_equal(calls["preregister"], [], "preserved gateway preregister calls")
assert_equal(calls["unlock"], ["pw_existing", "pw_existing"], "preserved gateway unlocks before preregister")
assert_equal(calls["open"], ["pw_existing", "pw_existing"], "preserved gateway opens local storage before preregister")
assert_equal(len(calls["tmux"]), 2, "preserved gateway command updates")
calls["preregister"].clear()
calls["unlock"].clear()
calls["open"].clear()
mod.TOKEN = None
mod.vault_exists = lambda: True
service_unlocked = {"value": False}
mod.gateway_is_unlocked = lambda: service_unlocked["value"]
service_available = {"value": False}
mod.gateway_is_unlocked = lambda: service_available["value"]
os.environ["NAPSEER_GATEWAY_PASSPHRASE"] = "pw_service"
os.environ["NAPSEER_GATEWAY_BOOTSTRAP_TOKEN"] = "npb_service"
mod.start_local_ui = lambda payload: {"status": "started", "payload": payload}
def service_unlock(passphrase):
calls["unlock"].append(passphrase)
def service_open(passphrase=None):
calls["open"].append(passphrase)
mod.TOKEN = "np_existing_worker"
service_unlocked["value"] = True
return {"status": "unlocked"}
service_available["value"] = True
return {"status": "local_available"}
mod.gateway_unlock = service_unlock
mod.gateway_open_local = service_open
mod.threading.Event = lambda: type("StopEvent", (), {"wait": lambda self: (_ for _ in ()).throw(KeyboardInterrupt())})()
service_result = mod.gateway_service_run({"timeout_seconds": 0})
assert_equal(service_result["status"], "started", "service run with preserved token")
assert_equal(calls["preregister"], [], "service run preserved gateway preregister calls")
assert_equal(calls["unlock"], ["pw_service"], "service run unlocks before preregister")
assert_equal(calls["open"], ["pw_service"], "service run opens local storage before preregister")
print("ok: gateway configure CLI/MCP parity smoke passed")
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
"""Smoke-test auth refresh while the gateway vault is locked."""
"""Smoke-test auth refresh with local gateway storage available."""
import importlib.util
import pathlib
@@ -20,8 +20,9 @@ def run():
mod = load_module()
writes = []
vault_writes = []
mod.VAULT_SECRETS = {}
mod.VAULT_KEY = None
mod.VAULT_KEY = b"k" * 32
mod.AUTH = {
"base_url": "https://api.example.test",
"project_id": "project_1",
@@ -35,7 +36,7 @@ def run():
mod.TOKEN = "expired"
mod.TOKEN_EXPIRES_AT = "old"
mod.vault_exists = lambda: True
mod.gateway_is_unlocked = lambda: False
mod.gateway_is_unlocked = lambda: True
mod.load_public_auth_file = lambda: {
"base_url": "https://api.example.test",
"project_id": "project_1",
@@ -46,10 +47,8 @@ def run():
}
mod.write_public_auth = lambda payload: writes.append(dict(payload))
def locked(operation="operation"):
raise RuntimeError(f"gateway is locked; unlock with the master passphrase before {operation}")
mod.require_unlocked = locked
mod.require_unlocked = lambda operation="operation": None
mod.write_vault_with_key = lambda key, payload: vault_writes.append((key, payload))
mod.save_auth({"token": "fresh", "token_expires_at": "new", "worker_id": "worker_1"})
assert writes[-1]["token"] == "fresh"
@@ -71,14 +70,11 @@ def run():
assert mod.TOKEN == "newer"
assert mod.TOKEN_EXPIRES_AT == "later"
try:
mod.save_auth({"gateway_default_command": "bash -l"})
except RuntimeError as exc:
assert "updating gateway vault" in str(exc)
else:
raise AssertionError("gateway vault updates must still require unlock")
mod.save_auth({"gateway_default_command": "bash -l"})
assert vault_writes[-1][0] == b"k" * 32
assert vault_writes[-1][1]["secrets"]["gateway_default_command"] == "bash -l"
print("ok: locked gateway auth refresh smoke passed")
print("ok: local gateway auth refresh smoke passed")
if __name__ == "__main__":
+69
View File
@@ -0,0 +1,69 @@
#!/usr/bin/env python3
"""Smoke-test local gateway storage uses a machine-local key, not interactive unlock."""
import importlib.util
import pathlib
import sys
import tempfile
def load_module():
script_path = pathlib.Path(__file__).resolve().parents[1] / "resources" / "scripts" / "napseer_mcp_server.py"
sys.path.insert(0, str(script_path.parent))
spec = importlib.util.spec_from_file_location("napseer_mcp_server_local_vault_test", script_path)
module = importlib.util.module_from_spec(spec)
assert spec and spec.loader
spec.loader.exec_module(module)
return module
def run():
mod = load_module()
with tempfile.TemporaryDirectory() as tmp:
state = pathlib.Path(tmp)
mod.AUTH_DIR = state
mod.AUTH_PATH = state / "auth.json"
mod.VAULT_PATH = state / "vault.json"
mod.LOCAL_VAULT_KEY_PATH = state / "vault.local-key"
mod.GATEWAY_RELAY_SECRET_PATH = state / "gateway-relay-secret.json"
mod.GATEWAY_RELAY_STATE_PATH = state / "gateway-relay-state.json"
mod.CONTAINER_IDENTITY_PATH = state / "container-identity.json"
mod.TELEMETRY_PATH = state / "telemetry.json"
auth = {
"base_url": "https://api.example.test",
"project_id": "project-1",
"token": "token",
"token_expires_at": "later",
"ssh_key_path": str(state / "id_ed25519"),
}
mod.AUTH = dict(auth)
mod.BASE_URL = auth["base_url"]
mod.DEFAULT_PROJECT_ID = auth["project_id"]
mod.TOKEN = auth["token"]
mod.TOKEN_EXPIRES_AT = auth["token_expires_at"]
mod.load_auth = lambda public_override=None, secret_override=None: {
**auth,
**(public_override or {}),
**(secret_override or {}),
}
mod.ensure_gateway_worker_capability = lambda refresh=True: {"status": "updated"}
result = mod.gateway_setup({"passphrase": "relay-passphrase", "default_command": "bash -l"})
assert result["status"] == "local_available"
assert mod.LOCAL_VAULT_KEY_PATH.exists()
assert mod.GATEWAY_RELAY_SECRET_PATH.exists()
assert mod.read_vault(mod.LOCAL_VAULT_KEY_PATH.read_text(encoding="utf-8").strip())["secrets"]["gateway_default_command"] == "bash -l"
mod.VAULT_SECRETS = {}
mod.VAULT_KEY = None
mod.GATEWAY_UNLOCKED = False
opened = mod.gateway_open_local()
assert opened["status"] == "local_available"
assert mod.VAULT_SECRETS["gateway_default_command"] == "bash -l"
print("ok: local gateway vault key smoke passed")
if __name__ == "__main__":
run()
+1 -2
View File
@@ -321,8 +321,7 @@ def run():
mod.vault_exists = lambda: True
cache_secret(mod, version=4, active=False)
assert mod.MEMORY_SECRET_CACHE
locked = mod.gateway_lock()
assert locked["status"] == "locked"
mod.clear_gateway_runtime_caches()
assert mod.MEMORY_SECRET_CACHE == {}
assert mod.ACTIVE_MEMORY_SECRET_VERSIONS == {}