"""Shared fixtures for dedicated Hermes node-account contracts.""" from __future__ import annotations import base64 import importlib.util import os import sys from pathlib import Path ROOT = Path(__file__).parents[2] SCRIPT = ROOT / "services/hermes/scripts/node_account_hardening.py" sys.path.insert(0, str(SCRIPT.parent)) def _key(material: bytes, comment: str = "") -> str: key_type = b"ssh-ed25519" blob = len(key_type).to_bytes(4, "big") + key_type + material suffix = f" {comment}" if comment else "" return "ssh-ed25519 " + base64.b64encode(blob).decode() + suffix def _typed_key(key_type: str, material: bytes, comment: str = "") -> str: encoded_type = key_type.encode() blob = len(encoded_type).to_bytes(4, "big") + encoded_type + material suffix = f" {comment}" if comment else "" return f"{key_type} {base64.b64encode(blob).decode()}{suffix}" def _load(): spec = importlib.util.spec_from_file_location("node_account_hardening_test", SCRIPT) assert spec and spec.loader module = importlib.util.module_from_spec(spec) sys.modules[spec.name] = module spec.loader.exec_module(module) return module def _fixture(tmp_path: Path, monkeypatch): module = _load() host_etc = tmp_path / "etc" host_home = tmp_path / "home" host_etc.mkdir() host_home.mkdir() originals = { "passwd": ( "root:x:0:0:root:/root:/bin/bash\n" "atlas:x:2000:2000:Atlas:/home/atlas:/bin/bash\n" "oceanus:x:2001:2001:Oceanus:/home/oceanus:/bin/bash\n" ), "group": ( "root:x:0:\n" "atlas:x:2000:\n" "oceanus:x:2001:\n" "disk:x:6:atlas\n" "sudo:x:27:oceanus\n" ), "shadow": ( "root:!:1:0:99999:7:::\n" "atlas:!:1:0:99999:7:::\n" "oceanus:!:1:0:99999:7:::\n" ), "gshadow": ( "root:!::\n" "atlas:!::\n" "oceanus:!::\n" "disk:!::atlas\n" "sudo:!::oceanus\n" ), } for name, value in originals.items(): (host_etc / name).write_text(value, encoding="utf-8") key = _key(b"synthetic-hermes-key") other = _key(b"human-operator-key") for user in ("atlas", "oceanus"): ssh = host_home / user / ".ssh" ssh.mkdir(parents=True) (ssh / "authorized_keys").write_text( f"{other} {user}\n{key}\n", encoding="utf-8" ) public_key = tmp_path / "public-key" public_key.write_text(key + "\n", encoding="utf-8") monkeypatch.setattr(module, "HOST_ETC", host_etc) monkeypatch.setattr(module, "HOST_HOME", host_home) monkeypatch.setattr(module, "ACCOUNT_UID", os.getuid()) monkeypatch.setattr(module, "ACCOUNT_GID", os.getgid()) monkeypatch.setattr(module, "HOST_ROOT_UID", os.getuid()) monkeypatch.setattr(module, "HOST_POLKIT_SHARE", tmp_path / "missing-polkit") monkeypatch.setattr(module, "_deny_sensitive_roots", lambda: None) return module, originals, key, other, public_key