Files
hermes-agent/tests/hermes_cli/test_ssh_session_token_parser.py
ethernet 59624b7ace tests: replace every bare host skipif with platforms()
The OS lanes are marker-driven: list_os_marked_tests.py picks the files
a lane imports from their platforms() specs and the lane selects with
-m platforms. A test gated with skipif(sys.platform != "win32") is
therefore never imported on the Windows lane and skipped everywhere else
— it runs on no host. skipif(sys.platform == "win32") tests were merely
invisible to the lane bookkeeping, but the rule the tree now follows is
one host marker, never a bare skipif.

Mechanical mapping, semantics preserved: skip-on-Windows → "posix",
skip-off-Windows → "windows", skip-off-Linux → "linux", skip-on-macOS →
"not macos". The former skip reasons stay as trailing comments. A
non-host condition (os.geteuid() == 0) stays a separate skipif beside
the marker, spelled getattr(os, "geteuid", ...) so the decorator still
imports on Windows.

Where the conversion would stack two platforms() marks on one test (the
conftest rejects that at collection) the narrower mark wins:
- test_update_wedged_gateway: the class is already platforms("linux");
  its per-test "needs UNIX sockets" marks were redundant and are gone.
- test_process_registry.TestSystemdCgroupIsolation: the class-level
  skip-on-Windows moves onto the 11 methods that had no host mark; the
  11 platforms("linux") methods keep theirs.
- test_file_ops_single_roundtrip: the two fifo tests drop their
  platforms("linux") in favour of the module's "posix" (mkfifo exists on
  macOS; both tests already skip when it does not).
- test_linux_desktop_entry / test_gateway_job_teardown_live: duplicate
  or wider marks removed.
2026-09-21 19:18:15 -04:00

149 lines
5.8 KiB
Python

import argparse
import os
import pytest
from hermes_constants import set_hermes_home_override, reset_hermes_home_override
from hermes_cli.main import cmd_dashboard
from hermes_cli.main_dashboard import _read_ssh_session_token_file
from hermes_cli.subcommands.dashboard import build_dashboard_parser
def dashboard_parser():
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers(dest="command")
build_dashboard_parser(
subparsers,
cmd_dashboard=lambda _args: None,
cmd_dashboard_register=lambda _args: None,
)
return parser
def test_serve_help_advertises_secure_ssh_bootstrap_flags(capsys):
with pytest.raises(SystemExit) as exit_info:
dashboard_parser().parse_args(["serve", "--help"])
assert exit_info.value.code == 0
output = capsys.readouterr().out
assert "--ssh-session-token-file PATH" in output
assert "--ssh-owner-nonce NONCE" in output
@pytest.mark.platforms("posix") # POSIX fixture uses mode bits; Windows read_token requires protected DACLs
def test_token_file_is_read_and_unlinked_through_private_directory(tmp_path, monkeypatch):
home = tmp_path / "home"
monkeypatch.setenv("HOME", str(home))
hermes_home = home / ".hermes"
token_dir = hermes_home / "desktop-ssh" / ("a" * 32)
token_dir.mkdir(parents=True, mode=0o700)
token_path = token_dir / "0123456789abcdef.token"
token_path.write_text("b" * 64)
token_path.chmod(0o600)
override = set_hermes_home_override(hermes_home)
try:
assert _read_ssh_session_token_file(str(token_path)) == "b" * 64
assert not token_path.exists()
finally:
reset_hermes_home_override(override)
@pytest.mark.platforms("posix") # POSIX desktop-ssh token path
def test_token_anchor_is_os_home_not_active_profile(tmp_path, monkeypatch):
"""Regression for #69551: the Desktop client always writes the token under
``$HOME/.hermes/desktop-ssh`` (a literal ``~/.hermes/desktop-ssh`` in
apps/desktop/electron/remote-lifecycle.ts, expanded against the account's
$HOME). A non-default sticky profile re-homes ``get_hermes_home()`` to
``<root>/profiles/<name>``, and a Docker-style ``HERMES_HOME`` can point
elsewhere entirely — neither must move the validator off
``$HOME/.hermes/desktop-ssh``, or the token is wrongly rejected."""
home = tmp_path / "home"
monkeypatch.setenv("HOME", str(home))
token_dir = home / ".hermes" / "desktop-ssh" / ("a" * 32)
token_dir.mkdir(parents=True, mode=0o700)
token_path = token_dir / "0123456789abcdef.token"
# A sticky profile and a custom (Docker) root both point get_hermes_home()
# away from $HOME/.hermes; the anchor must ignore both.
for elsewhere in (home / ".hermes" / "profiles" / "coder", tmp_path / "opt" / "data"):
token_path.write_text("b" * 64)
token_path.chmod(0o600)
override = set_hermes_home_override(elsewhere)
try:
assert _read_ssh_session_token_file(str(token_path)) == "b" * 64
assert not token_path.exists()
finally:
reset_hermes_home_override(override)
@pytest.mark.platforms("posix") # POSIX desktop-ssh token path
def test_token_under_profile_desktop_ssh_is_rejected(tmp_path, monkeypatch):
"""The client never writes under a profile-scoped desktop-ssh dir, so a token
placed there must be rejected even while that profile is active — proving the
anchor is the OS home, not the active profile (#69551)."""
home = tmp_path / "home"
monkeypatch.setenv("HOME", str(home))
profile_home = home / ".hermes" / "profiles" / "coder"
token_dir = profile_home / "desktop-ssh" / ("a" * 32)
token_dir.mkdir(parents=True, mode=0o700)
token_path = token_dir / "0123456789abcdef.token"
token_path.write_text("b" * 64)
token_path.chmod(0o600)
override = set_hermes_home_override(profile_home)
try:
with pytest.raises(SystemExit, match="desktop-ssh directory"):
_read_ssh_session_token_file(str(token_path))
finally:
reset_hermes_home_override(override)
@pytest.mark.platforms("posix") # POSIX symlink contract
def test_token_file_rejects_symlink(tmp_path, monkeypatch):
home = tmp_path / "home"
monkeypatch.setenv("HOME", str(home))
token_dir = home / ".hermes" / "desktop-ssh" / ("a" * 32)
token_dir.mkdir(parents=True, mode=0o700)
target = tmp_path / "token"
target.write_text("b" * 64)
target.chmod(0o600)
token_path = token_dir / "0123456789abcdef.token"
token_path.symlink_to(target)
override = set_hermes_home_override(home / ".hermes")
try:
with pytest.raises(SystemExit, match="symlink|not accessible"):
_read_ssh_session_token_file(str(token_path))
assert not token_path.exists()
assert target.read_text() == "b" * 64
finally:
reset_hermes_home_override(override)
@pytest.mark.platforms("linux")
def test_token_file_rejects_parent_escape(tmp_path, monkeypatch):
home = tmp_path / "home"
monkeypatch.setenv("HOME", str(home))
token_root = home / ".hermes" / "desktop-ssh"
token_root.mkdir(parents=True, mode=0o700)
escaped = token_root.parent / "0123456789abcdef.token"
escaped.write_text("b" * 64)
escaped.chmod(0o600)
override = set_hermes_home_override(home / ".hermes")
try:
with pytest.raises(SystemExit, match="invalid runtime path"):
_read_ssh_session_token_file(str(token_root / ".." / escaped.name))
assert escaped.exists()
finally:
reset_hermes_home_override(override)
def test_windows_runtime_root_stays_at_machine_root_for_named_profile(tmp_path, monkeypatch):
from hermes_cli import windows_ssh_runtime
machine_root = tmp_path / "custom-hermes-root"
monkeypatch.setenv("HERMES_HOME", str(machine_root / "profiles" / "writer_2"))
assert windows_ssh_runtime._root() == machine_root / "desktop-ssh"