6270d8c956
Testing / remote-protocol-compat (0.16.0) (push) Successful in 1m1s
Testing / remote-protocol-compat (0.15.0) (push) Successful in 1m3s
Testing / test (push) Failing after 1m15s
Build & Publish Package / publish (push) Successful in 51s
Package Extension / package-extension (push) Successful in 1m6s
- Add SSH-style server identity keys and known-host verification for remote serve endpoints. - Add remote add/list/remove commands for explicit endpoint persistence. - Fix remote clients listing to fan out through target discovery instead of ambiguous auto-routing. - Add URL glob matching for tabs filter and count with extension tests. - Add n8n credential pinning for server public keys or SHA256 fingerprints. - Remove obsolete compat shim behavior while keeping empty compat seams for future protocol changes. - Bump browser-cli to 0.16.4 and n8n node to 0.3.1. - Cover known-hosts, remote registry, compat seams, n8n protocol verification, and URL matching with tests.
36 lines
1.4 KiB
Python
36 lines
1.4 KiB
Python
"""Challenge-frame helpers for ``browser-cli serve``."""
|
|
from __future__ import annotations
|
|
|
|
import asyncio
|
|
import secrets
|
|
from pathlib import Path
|
|
|
|
from browser_cli.version_manager import PROTOCOL_MIN_CLIENT, get_installed_version
|
|
|
|
async def load_auth_keys(auth_keys_path: Path | None) -> list[str] | None:
|
|
if auth_keys_path is None:
|
|
return None
|
|
from browser_cli.auth import load_authorized_keys
|
|
return await asyncio.to_thread(load_authorized_keys, auth_keys_path)
|
|
|
|
async def build_challenge(auth_keys_path: Path | None) -> tuple[str, object | None, dict]:
|
|
nonce = secrets.token_hex(32)
|
|
pq_private_key = None
|
|
challenge_msg = {
|
|
"type": "challenge",
|
|
"nonce": nonce,
|
|
"server_version": get_installed_version(),
|
|
"min_client_version": PROTOCOL_MIN_CLIENT,
|
|
}
|
|
if auth_keys_path is not None:
|
|
from browser_cli.auth import PQ_KEX_ALG, pq_kex_server_keypair
|
|
pq_keypair = await asyncio.to_thread(pq_kex_server_keypair)
|
|
if pq_keypair is not None:
|
|
pq_private_key, pq_public_key = pq_keypair
|
|
challenge_msg["pq_kex"] = {"alg": PQ_KEX_ALG, "public_key": pq_public_key.hex()}
|
|
from browser_cli.auth.server_identity import load_or_create_server_identity, public_key_hex, sign_challenge
|
|
server_key = await asyncio.to_thread(load_or_create_server_identity)
|
|
challenge_msg["server_pubkey"] = public_key_hex(server_key)
|
|
challenge_msg["server_sig"] = sign_challenge(challenge_msg, server_key)
|
|
return nonce, pq_private_key, challenge_msg
|