From caa6b73336dea975ab211fbe8cbff36eafa75773 Mon Sep 17 00:00:00 2001 From: Brad Stein Date: Wed, 28 Jan 2026 18:29:49 -0300 Subject: [PATCH] comms: source admin token from seeder access tokens --- .../oneoffs/synapse-admin-ensure-job.yaml | 97 ++++--------------- 1 file changed, 20 insertions(+), 77 deletions(-) diff --git a/services/comms/oneoffs/synapse-admin-ensure-job.yaml b/services/comms/oneoffs/synapse-admin-ensure-job.yaml index 3241e35..bd397f4 100644 --- a/services/comms/oneoffs/synapse-admin-ensure-job.yaml +++ b/services/comms/oneoffs/synapse-admin-ensure-job.yaml @@ -1,12 +1,12 @@ # services/comms/oneoffs/synapse-admin-ensure-job.yaml -# One-off job for comms/synapse-admin-ensure-11. -# Purpose: synapse admin ensure 11 (see container args/env in this file). +# One-off job for comms/synapse-admin-ensure-12. +# Purpose: synapse admin ensure 12 (see container args/env in this file). # Run by setting spec.suspend to false, reconcile, then set it back to true. # Safe to delete the finished Job/pod; it should not run continuously. apiVersion: batch/v1 kind: Job metadata: - name: synapse-admin-ensure-11 + name: synapse-admin-ensure-12 namespace: comms spec: suspend: false @@ -49,14 +49,10 @@ spec: python - <<'PY' import json import os - import secrets - import string - import time import urllib.error import urllib.parse import urllib.request - import bcrypt import psycopg2 VAULT_ADDR = os.environ.get("VAULT_ADDR", "http://vault.vault.svc.cluster.local:8200").rstrip("/") @@ -112,51 +108,16 @@ spec: headers={"X-Vault-Token": token, "Content-Type": "application/json"}, method="POST", ) - with urllib.request.urlopen(req, timeout=30) as resp: - resp.read() - - def random_password(length: int = 32) -> str: - alphabet = string.ascii_letters + string.digits - return "".join(secrets.choice(alphabet) for _ in range(length)) + with urllib.request.urlopen(req, timeout=30) as resp: + resp.read() def ensure_admin_creds(token: str) -> dict: data = vault_get(token, "comms/synapse-admin") - username = (data.get("username") or "").strip() or "synapse-admin" - password = (data.get("password") or "").strip() - if not password: - password = random_password() + username = (data.get("username") or "").strip() or "othrys-seeder" data["username"] = username - data["password"] = password vault_put(token, "comms/synapse-admin", data) return data - def ensure_user(cur, cols, user_id, password, admin): - now_ms = int(time.time() * 1000) - values = { - "name": user_id, - "password_hash": bcrypt.hashpw(password.encode(), bcrypt.gensalt()).decode(), - "creation_ts": now_ms, - } - - def add_flag(name, flag): - if name not in cols: - return - if cols[name]["type"] in ("smallint", "integer"): - values[name] = int(flag) - else: - values[name] = bool(flag) - - add_flag("admin", admin) - add_flag("deactivated", False) - add_flag("shadow_banned", False) - add_flag("is_guest", False) - - columns = list(values.keys()) - placeholders = ", ".join(["%s"] * len(columns)) - updates = ", ".join([f"{col}=EXCLUDED.{col}" for col in columns if col != "name"]) - query = f"INSERT INTO users ({', '.join(columns)}) VALUES ({placeholders}) ON CONFLICT (name) DO UPDATE SET {updates};" - cur.execute(query, [values[c] for c in columns]) - def get_cols(cur): cur.execute( """ @@ -174,33 +135,6 @@ spec: } return cols - def ensure_access_token(cur, user_id, token_value): - cur.execute("SELECT COALESCE(MAX(id), 0) + 1 FROM access_tokens") - token_id = cur.fetchone()[0] - cur.execute( - """ - INSERT INTO access_tokens (id, user_id, token, device_id, valid_until_ms) - VALUES (%s, %s, %s, %s, NULL) - ON CONFLICT (token) DO NOTHING - """, - (token_id, user_id, token_value, "ariadne-admin"), - ) - - def ensure_device(cur, user_id, device_id): - cur.execute( - "SELECT 1 FROM devices WHERE user_id = %s AND device_id = %s", - (user_id, device_id), - ) - if cur.fetchone(): - return - cur.execute( - """ - INSERT INTO devices (user_id, device_id, display_name, last_seen, ip, user_agent, hidden) - VALUES (%s, %s, %s, %s, NULL, NULL, FALSE) - """, - (user_id, device_id, "ariadne-admin", int(time.time() * 1000)), - ) - def admin_token_valid(token: str, user_id: str) -> bool: if not token or not SYNAPSE_ADMIN_URL: return False @@ -242,15 +176,24 @@ spec: user=PGUSER, password=pg_password, ) - token_value = f"syt_{secrets.token_urlsafe(32)}" - device_id = "ariadne-admin" try: with conn: with conn.cursor() as cur: cols = get_cols(cur) - ensure_user(cur, cols, user_id, admin_data["password"], True) - ensure_device(cur, user_id, device_id) - ensure_access_token(cur, user_id, token_value) + if "admin" not in cols: + raise RuntimeError("users.admin column missing") + cur.execute( + """ + SELECT token FROM access_tokens + WHERE user_id = %s AND valid_until_ms IS NULL + ORDER BY id DESC LIMIT 1 + """, + (user_id,), + ) + row = cur.fetchone() + if not row: + raise RuntimeError(f"no access token found for {user_id}") + token_value = row[0] finally: conn.close()