91 lines
3.0 KiB
Python
91 lines
3.0 KiB
Python
"""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
|