Files
felhom.eu/documentation/audits/family-gate-2026-10-02/tools/fg_setup.py
T

38 lines
2.7 KiB
Python

#!/usr/bin/env python3
"""fg_setup.py — on 9202 (controller 0.287.0, drill catalog): two family members through the dashboard's Család card
(POST /family/members/add — the card's own call), then MeTube and Grimmory installed through the product, and Grimmory's
first admin made by the household through the SETUP gate (it is setup-gated AND family-gated). Secrets → 0600 scratch."""
import json, os, re, subprocess, sys, time
from fg import *
SC = w.SC
log = open(f"{w.EV}/setup.txt", "a", buffering=1)
def say(*a):
w.say(*a); log.write(" ".join(map(str, a)) + "\n")
w.login()
say(f"##### family gate live setup on 9202 — controller {w.guest('docker inspect felhom-controller --format {{.Config.Image}}').strip()} | {time.strftime('%FT%TZ', time.gmtime())}")
sess = dash_session(); csrf = open(f"{SC}/csrf{os.getpid()}.txt").read().strip()
fam = {}
for name in ("anna", "bela"):
r = subprocess.run(["curl", "-sk", "-H", f"Host: {CTL}", "-H", f"Cookie: {sess}", "-H", f"X-CSRF-Token: {csrf}",
"-X", "POST", "--data", f"name={name}", f"{w.BASE}/family/members/add"], capture_output=True, text=True)
d = json.loads(r.stdout)
fam[name] = d["data"]["password"]
say(f"Család card: add {name} -> ok={d['ok']} members={d['data']['members']} password returned ONCE (len {len(fam[name])}, not printed)")
r = subprocess.run(["curl", "-sk", "-H", f"Host: {CTL}", "-H", f"Cookie: {sess}", f"{w.BASE}/settings/security"], capture_output=True, text=True)
say("the security page carries the card:", 'id="family-card"' in r.stdout, "| and no member password:", not any(p in r.stdout for p in fam.values()))
json.dump(fam, open(f"{SC}/fam.json", "w")); os.chmod(f"{SC}/fam.json", 0o600)
for app, sub in (("metube", "video"), ("grimmory", "library")):
say(f"deploy {app} ->", w.deploy(app, sub))
say(f" {app} family-gate file:", w.guest(f"ls /opt/docker/stacks/traefik/dynamic/ | grep -E 'family-gate-{app}|setup-gate-{app}' | tr '\\n' ' '"))
w.wait_app("library", "/api/v1/healthcheck", want=("200",), tries=90)
pw = "Gm-" + __import__("secrets").token_hex(10)
c, h, b = lan(f"library.{DOM}", "/api/v1/setup", method="POST", cookie=w.gate_cookie("library"),
hdrs=("Content-Type: application/json",), data=json.dumps({"username": "admin", "password": pw, "email": "admin@felhom.invalid", "name": "Felhom"}))
say("grimmory: the household makes the first admin THROUGH THE SETUP GATE ->", c)
json.dump({"admin_pw": pw}, open(f"{SC}/gm.json", "w")); os.chmod(f"{SC}/gm.json", 0o600)
for i in range(40):
files = w.guest("ls /opt/docker/stacks/traefik/dynamic/ | grep -E 'grimmory' | tr '\\n' ' '")
if "setup-gate-grimmory" not in files: break
time.sleep(5)
say(f"grimmory: setup gate opened by its probe after ~{5*i} s; files now: {files}")