hololake-system-architecture/product-source/hololake-platform/guanghu-os/scripts/native-public-projection-relay.py

98 lines
3.4 KiB
Python
Raw Normal View History

#!/usr/bin/env python3
"""Project a fresh protected native-relay receipt through one pinned SSH route."""
from __future__ import annotations
import argparse
import os
import pathlib
import subprocess
import time
def parse_receipt(path: pathlib.Path) -> tuple[dict[str, str], float]:
if path.is_symlink():
raise ValueError("relay receipt cannot be a symlink")
stat = path.stat()
values: dict[str, str] = {}
for line in path.read_text(encoding="utf-8").splitlines():
if not line or line[:1].isspace() or ": " not in line:
continue
key, value = line.split(": ", 1)
if key in values:
raise ValueError(f"duplicate relay receipt key: {key}")
values[key] = value
return values, time.time() - stat.st_mtime
def projection_action(
values: dict[str, str], age: float, max_age: float, expected_source: str
) -> str:
ready = (
age >= -5
and age <= max_age
and values.get("schema")
== "guanghu.physical-native-final-resident-relay/v1"
and values.get("status") == "READY_NATIVE_RESIDENT"
and values.get("recovery_capability_sent") == "false"
and values.get("acknowledged_sequences") == "1,2,3,4,5,6"
and values.get("observed_nat_sources") == expected_source
)
return "ready" if ready else "dormant"
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--relay-receipt", required=True)
parser.add_argument("--max-receipt-age-seconds", type=float, default=15.0)
parser.add_argument("--expected-nat-source", required=True)
parser.add_argument("--node", required=True)
parser.add_argument("--relay", required=True)
parser.add_argument("--candidate-sha256", required=True)
parser.add_argument("--source-commit", required=True)
parser.add_argument("--ssh-bin", default="/usr/bin/ssh")
parser.add_argument("--ssh-config", required=True)
parser.add_argument("--ssh-target", required=True)
args = parser.parse_args()
if args.max_receipt_age_seconds <= 0:
raise SystemExit("max receipt age must be greater than zero")
ssh_bin = pathlib.Path(args.ssh_bin)
ssh_config = pathlib.Path(args.ssh_config)
if not ssh_bin.is_absolute() or not os.access(ssh_bin, os.X_OK):
raise SystemExit("SSH binary must be an executable absolute path")
if not ssh_config.is_absolute() or not ssh_config.is_file():
raise SystemExit("SSH config must be an existing absolute file")
try:
values, age = parse_receipt(pathlib.Path(args.relay_receipt))
action = projection_action(
values,
age,
args.max_receipt_age_seconds,
args.expected_nat_source,
)
except (OSError, UnicodeError, ValueError):
action = "dormant"
command = [
str(ssh_bin),
"-F",
str(ssh_config),
"-o",
"BatchMode=yes",
"-o",
"ConnectTimeout=5",
args.ssh_target,
action,
args.node,
args.candidate_sha256,
args.source_commit,
args.relay,
]
completed = subprocess.run(command, check=False, timeout=10)
if completed.returncode != 0:
raise SystemExit("native projection transport failed closed")
print(f"NATIVE_PUBLIC_PROJECTION_RELAY_OK action={action}")
return 0
if __name__ == "__main__":
raise SystemExit(main())