#!/usr/bin/env python3 """Host110-only SigNoz v0.113 first-admin and metadata PAT provisioner. The program is streamed to ``python3 -`` by Agent99. Secrets are generated and used only in this process; stdout contains a bounded metadata-only JSON object. """ from __future__ import annotations import argparse import http.client import json import os import secrets import stat import sys import urllib.error import urllib.request from pathlib import Path from typing import Any BASE_URL = "http://127.0.0.1:8080" CREDENTIAL_PATH = Path("/etc/awoooi/secrets/signoz-metadata-api-key") RECOVERY_PASSWORD_PATH = Path( "/etc/awoooi/secrets/signoz-bootstrap-admin-password.recovery" ) ADMIN_EMAIL = "awoooi-signoz-admin@example.invalid" ORG_NAME = "AWOOOI" PAT_NAME = "awoooi-metadata-export" MAX_RESPONSE_BYTES = 1024 * 1024 EXPECTED_UID = 0 class ProvisionError(RuntimeError): pass def request_json( method: str, path: str, payload: dict[str, Any] | None = None, *, bearer: str | None = None, api_key: str | None = None, ) -> dict[str, Any]: headers = {"Accept": "application/json"} body = None if payload is not None: headers["Content-Type"] = "application/json" body = json.dumps(payload, separators=(",", ":")).encode("utf-8") if bearer: headers["Authorization"] = f"Bearer {bearer}" if api_key: headers["SIGNOZ-API-KEY"] = api_key request = urllib.request.Request( f"{BASE_URL}{path}", data=body, headers=headers, method=method ) try: with urllib.request.urlopen(request, timeout=15) as response: # nosec B310 raw = response.read(MAX_RESPONSE_BYTES + 1) except urllib.error.HTTPError as exc: raise ProvisionError(f"http_{method.lower()}_{path.rsplit('/', 1)[-1]}_{exc.code}") from None except (urllib.error.URLError, TimeoutError, OSError, http.client.HTTPException): raise ProvisionError(f"transport_{method.lower()}_{path.rsplit('/', 1)[-1]}_failed") from None if len(raw) > MAX_RESPONSE_BYTES: raise ProvisionError("response_too_large") try: value = json.loads(raw) except (UnicodeError, json.JSONDecodeError): raise ProvisionError("response_json_invalid") from None if not isinstance(value, dict) or value.get("status") != "success": raise ProvisionError("response_status_invalid") return value def request_version() -> dict[str, Any]: request = urllib.request.Request(f"{BASE_URL}/api/v1/version", method="GET") try: with urllib.request.urlopen(request, timeout=15) as response: # nosec B310 raw = response.read(MAX_RESPONSE_BYTES + 1) except ( urllib.error.HTTPError, urllib.error.URLError, TimeoutError, OSError, http.client.HTTPException, ): raise ProvisionError("version_request_failed") from None if len(raw) > MAX_RESPONSE_BYTES: raise ProvisionError("version_response_too_large") try: value = json.loads(raw) except (UnicodeError, json.JSONDecodeError): raise ProvisionError("version_response_invalid") from None if not isinstance(value, dict): raise ProvisionError("version_shape_invalid") return value def request_no_content( method: str, path: str, *, bearer: str | None = None, api_key: str | None = None, ) -> None: headers = {"Accept": "application/json"} if bearer: headers["Authorization"] = f"Bearer {bearer}" if api_key: headers["SIGNOZ-API-KEY"] = api_key request = urllib.request.Request( f"{BASE_URL}{path}", headers=headers, method=method ) try: with urllib.request.urlopen(request, timeout=15) as response: # nosec B310 status = response.status raw = response.read(1) except urllib.error.HTTPError as exc: raise ProvisionError(f"http_{method.lower()}_{path.rsplit('/', 1)[-1]}_{exc.code}") from None except (urllib.error.URLError, TimeoutError, OSError, http.client.HTTPException): raise ProvisionError(f"transport_{method.lower()}_{path.rsplit('/', 1)[-1]}_failed") from None if status != 204 or raw: raise ProvisionError("no_content_response_invalid") def secret_state(path: Path, *, read_value: bool = False) -> tuple[str, str | None]: try: metadata = path.lstat() except FileNotFoundError: return "absent", None if not stat.S_ISREG(metadata.st_mode) or metadata.st_uid != EXPECTED_UID: raise ProvisionError("credential_not_root_regular_file") if stat.S_IMODE(metadata.st_mode) not in (0o400, 0o600): raise ProvisionError("credential_mode_invalid") if metadata.st_size <= 0 or metadata.st_size > 4096: raise ProvisionError("credential_size_invalid") if not read_value: return "present", None token = path.read_text(encoding="utf-8").strip() if not token or len(token) > 4096 or any(ch.isspace() for ch in token): raise ProvisionError("credential_value_invalid") return "present", token def credential_state(*, read_value: bool = False) -> tuple[str, str | None]: return secret_state(CREDENTIAL_PATH, read_value=read_value) def setup_completed() -> bool: value = request_version() data = value.get("data", value) if not isinstance(data, dict): raise ProvisionError("version_shape_invalid") completed = data.get("setupCompleted") if not isinstance(completed, bool): raise ProvisionError("setup_state_missing") return completed def verify_key(token: str, *, expected_pat_id: str | None = None) -> None: value = request_json("GET", "/api/v1/dashboards", api_key=token) if not isinstance(value.get("data"), (list, dict)): raise ProvisionError("credential_dashboard_readback_invalid") roles = request_json("GET", "/api/v1/roles", api_key=token) if not isinstance(roles.get("data"), list): raise ProvisionError("credential_admin_role_readback_invalid") if expected_pat_id: pats = request_json("GET", "/api/v1/pats", api_key=token) pat_rows = pats.get("data") if not isinstance(pat_rows, list) or not any( isinstance(row, dict) and row.get("id") == expected_pat_id for row in pat_rows ): raise ProvisionError("credential_admin_pat_readback_invalid") def write_secret_no_clobber(path: Path, value: str) -> None: parent = path.parent parent.mkdir(mode=0o700, parents=True, exist_ok=True) parent_metadata = parent.lstat() if not stat.S_ISDIR(parent_metadata.st_mode) or stat.S_ISLNK(parent_metadata.st_mode): raise ProvisionError("credential_parent_invalid") temp = parent / f".{path.name}.{os.getpid()}.{secrets.token_hex(8)}.tmp" fd = -1 try: fd = os.open(temp, os.O_WRONLY | os.O_CREAT | os.O_EXCL | os.O_NOFOLLOW, 0o600) os.write(fd, value.encode("utf-8")) os.fsync(fd) os.close(fd) fd = -1 os.chown(temp, 0, 0, follow_symlinks=False) os.chmod(temp, 0o400, follow_symlinks=False) os.link(temp, path, follow_symlinks=False) os.unlink(temp) except FileExistsError: raise ProvisionError("credential_destination_exists") from None finally: if fd >= 0: os.close(fd) try: temp.unlink() except FileNotFoundError: pass def remove_secret_verified(path: Path) -> None: try: metadata = path.lstat() except FileNotFoundError: return if not stat.S_ISREG(metadata.st_mode) or stat.S_ISLNK(metadata.st_mode): raise ProvisionError("secret_cleanup_target_invalid") try: path.unlink() except OSError: raise ProvisionError("secret_cleanup_delete_failed") from None try: path.lstat() except FileNotFoundError: return raise ProvisionError("secret_cleanup_residue_present") def organization_id_for_admin() -> str: value = request_json( "GET", "/api/v2/sessions/context?email=awoooi-signoz-admin%40example.invalid" ) data = value.get("data") orgs = data.get("orgs") if isinstance(data, dict) else None if not isinstance(orgs, list) or len(orgs) != 1 or not isinstance(orgs[0], dict): raise ProvisionError("bootstrap_recovery_org_context_invalid") org_id = orgs[0].get("id") or orgs[0].get("orgId") if not isinstance(org_id, str) or not org_id: raise ProvisionError("bootstrap_recovery_org_id_missing") return org_id def revoke_pat(access_token: str, pat_id: str, pat_token: str = "") -> bool: if access_token: try: request_no_content( "DELETE", f"/api/v1/pats/{pat_id}", bearer=access_token ) return True except ProvisionError: pass if pat_token: try: request_no_content( "DELETE", f"/api/v1/pats/{pat_id}", api_key=pat_token ) return True except ProvisionError: pass return False def close_session(access_token: str) -> bool: try: request_no_content("DELETE", "/api/v2/sessions", bearer=access_token) return True except ProvisionError: return False def rollback_created_pat( access_token: str, pat_id: str, pat_token: str, *, file_created: bool, ) -> None: revoked = revoke_pat(access_token, pat_id, pat_token) if pat_id else True if not revoked: raise ProvisionError("apply_failed_pat_revoke_unverified_credential_preserved") if file_created: remove_secret_verified(CREDENTIAL_PATH) def apply() -> dict[str, Any]: state, _ = credential_state() if state != "absent": raise ProvisionError("credential_already_present_no_clobber") recovery_state, recovery_password = secret_state( RECOVERY_PASSWORD_PATH, read_value=True ) completed = setup_completed() if recovery_state == "absent" and completed: raise ProvisionError("setup_already_completed_without_bootstrap_recovery") if recovery_state == "absent": recovery_password = secrets.token_urlsafe(48) write_secret_no_clobber(RECOVERY_PASSWORD_PATH, recovery_password) recovery_state = "present" if recovery_password is None: raise ProvisionError("bootstrap_recovery_password_missing") org_id = "" if not completed: try: registration = request_json( "POST", "/api/v1/register", { "email": ADMIN_EMAIL, "orgDisplayName": ORG_NAME, "password": recovery_password, }, ) registration_data = registration.get("data") org_id = ( registration_data.get("orgId") if isinstance(registration_data, dict) else None ) if not isinstance(org_id, str) or not org_id: raise ProvisionError("registration_org_id_missing") except ProvisionError: if not setup_completed(): raise org_id = organization_id_for_admin() else: org_id = organization_id_for_admin() session = request_json( "POST", "/api/v2/sessions/email_password", {"email": ADMIN_EMAIL, "password": recovery_password, "orgId": org_id}, ) recovery_password = "" session_data = session.get("data") access_token = session_data.get("accessToken") if isinstance(session_data, dict) else None if not isinstance(access_token, str) or not access_token: raise ProvisionError("session_access_token_missing") pat_id = "" token = "" file_created = False try: me = request_json("GET", "/api/v1/user/me", bearer=access_token) me_data = me.get("data") if not isinstance(me_data, dict) or me_data.get("role") != "ADMIN" or me_data.get("orgId") != org_id: raise ProvisionError("bootstrap_admin_identity_invalid") pat = request_json( "POST", "/api/v1/pats", {"name": PAT_NAME, "expiresInDays": 30, "role": "ADMIN"}, bearer=access_token, ) pat_data = pat.get("data") pat_id = pat_data.get("id") if isinstance(pat_data, dict) else None token = pat_data.get("token") if isinstance(pat_data, dict) else None if not isinstance(pat_id, str) or not pat_id or not isinstance(token, str) or not token: raise ProvisionError("pat_response_invalid") verify_key(token, expected_pat_id=pat_id) write_secret_no_clobber(CREDENTIAL_PATH, token) file_created = True _, persisted = credential_state(read_value=True) if persisted is None: raise ProvisionError("credential_persist_readback_missing") verify_key(persisted, expected_pat_id=pat_id) if not close_session(access_token): raise ProvisionError("session_cleanup_unverified") access_token = "" remove_secret_verified(RECOVERY_PASSWORD_PATH) token = "" except Exception as original: try: rollback_created_pat( access_token, pat_id, token, file_created=file_created, ) except ProvisionError as rollback_error: raise rollback_error from None finally: close_session(access_token) access_token = "" raise original return { "terminal": "applied_verified", "setup_completed": True, "admin_identity_verified": True, "credential_file_created": True, "credential_api_verified": True, "session_cleanup_verified": True, "bootstrap_recovery_removed": True, "bootstrap_is_permanent": True, } def main() -> int: parser = argparse.ArgumentParser() parser.add_argument("--mode", choices=("check", "apply", "verify"), required=True) args = parser.parse_args() try: if args.mode == "check": state, _ = credential_state() recovery_state, _ = secret_state(RECOVERY_PASSWORD_PATH) result = { "terminal": "check_pass_no_write", "setup_completed": setup_completed(), "credential_state": state, "bootstrap_recovery_state": recovery_state, "production_write": False, } elif args.mode == "apply": result = apply() else: state, token = credential_state(read_value=True) recovery_state, _ = secret_state(RECOVERY_PASSWORD_PATH) if ( state != "present" or token is None or not setup_completed() or recovery_state != "absent" ): raise ProvisionError("verify_precondition_failed") verify_key(token) token = "" result = { "terminal": "verify_pass", "setup_completed": True, "credential_state": "present", "credential_api_verified": True, } print(json.dumps(result, sort_keys=True, separators=(",", ":"))) return 0 except ProvisionError as exc: print( json.dumps( {"terminal": "failed", "error_code": str(exc)}, sort_keys=True, separators=(",", ":"), ) ) return 1 if __name__ == "__main__": raise SystemExit(main())