# services/comms/oneoffs/synapse-user-seed-job.yaml # One-off job for comms/synapse-user-seed-8. # Purpose: synapse user seed 8 (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-user-seed-8 namespace: comms spec: suspend: true backoffLimit: 1 ttlSecondsAfterFinished: 3600 template: metadata: annotations: vault.hashicorp.com/agent-inject: "true" vault.hashicorp.com/agent-pre-populate-only: "true" vault.hashicorp.com/role: "comms" vault.hashicorp.com/agent-inject-secret-turn-secret: "kv/data/atlas/comms/turn-shared-secret" vault.hashicorp.com/agent-inject-template-turn-secret: | {{- with secret "kv/data/atlas/comms/turn-shared-secret" -}}{{ .Data.data.TURN_STATIC_AUTH_SECRET }}{{- end -}} vault.hashicorp.com/agent-inject-secret-livekit-primary: "kv/data/atlas/comms/livekit-api" vault.hashicorp.com/agent-inject-template-livekit-primary: | {{- with secret "kv/data/atlas/comms/livekit-api" -}}{{ .Data.data.primary }}{{- end -}} vault.hashicorp.com/agent-inject-secret-bot-pass: "kv/data/atlas/comms/atlasbot-credentials-runtime" vault.hashicorp.com/agent-inject-template-bot-pass: | {{- with secret "kv/data/atlas/comms/atlasbot-credentials-runtime" -}}{{ index .Data.data "bot-password" }}{{- end -}} vault.hashicorp.com/agent-inject-secret-seeder-pass: "kv/data/atlas/comms/atlasbot-credentials-runtime" vault.hashicorp.com/agent-inject-template-seeder-pass: | {{- with secret "kv/data/atlas/comms/atlasbot-credentials-runtime" -}}{{ index .Data.data "seeder-password" }}{{- end -}} vault.hashicorp.com/agent-inject-secret-chat-matrix: "kv/data/atlas/shared/chat-ai-keys-runtime" vault.hashicorp.com/agent-inject-template-chat-matrix: | {{- with secret "kv/data/atlas/shared/chat-ai-keys-runtime" -}}{{ .Data.data.matrix }}{{- end -}} vault.hashicorp.com/agent-inject-secret-chat-homepage: "kv/data/atlas/shared/chat-ai-keys-runtime" vault.hashicorp.com/agent-inject-template-chat-homepage: | {{- with secret "kv/data/atlas/shared/chat-ai-keys-runtime" -}}{{ .Data.data.homepage }}{{- end -}} vault.hashicorp.com/agent-inject-secret-mas-admin-secret: "kv/data/atlas/comms/mas-admin-client-runtime" vault.hashicorp.com/agent-inject-template-mas-admin-secret: | {{- with secret "kv/data/atlas/comms/mas-admin-client-runtime" -}}{{ .Data.data.client_secret }}{{- end -}} vault.hashicorp.com/agent-inject-secret-synapse-db-pass: "kv/data/atlas/comms/synapse-db" vault.hashicorp.com/agent-inject-template-synapse-db-pass: | {{- with secret "kv/data/atlas/comms/synapse-db" -}}{{ .Data.data.POSTGRES_PASSWORD }}{{- end -}} vault.hashicorp.com/agent-inject-secret-mas-db-pass: "kv/data/atlas/comms/mas-db" vault.hashicorp.com/agent-inject-template-mas-db-pass: | {{- with secret "kv/data/atlas/comms/mas-db" -}}{{ .Data.data.password }}{{- end -}} vault.hashicorp.com/agent-inject-secret-mas-matrix-shared: "kv/data/atlas/comms/mas-secrets-runtime" vault.hashicorp.com/agent-inject-template-mas-matrix-shared: | {{- with secret "kv/data/atlas/comms/mas-secrets-runtime" -}}{{ .Data.data.matrix_shared_secret }}{{- end -}} vault.hashicorp.com/agent-inject-secret-mas-kc-secret: "kv/data/atlas/comms/mas-secrets-runtime" vault.hashicorp.com/agent-inject-template-mas-kc-secret: | {{- with secret "kv/data/atlas/comms/mas-secrets-runtime" -}}{{ .Data.data.keycloak_client_secret }}{{- end -}} spec: restartPolicy: Never affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: node-role.kubernetes.io/worker operator: Exists preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 preference: matchExpressions: - key: kubernetes.io/arch operator: In values: ["arm64"] serviceAccountName: comms-vault containers: - name: seed image: python:3.11-slim env: - name: PGHOST value: postgres-service.postgres.svc.cluster.local - name: PGPORT value: "5432" - name: PGDATABASE value: synapse - name: PGUSER value: synapse - name: SEEDER_USER value: othrys-seeder - name: BOT_USER value: atlasbot command: - /bin/sh - -c - | set -euo pipefail . /vault/scripts/comms_vault_env.sh pip install --no-cache-dir psycopg2-binary bcrypt >/dev/null python - <<'PY' import os import time import bcrypt import psycopg2 def get_cols(cur): cur.execute( """ SELECT column_name, is_nullable, column_default, data_type FROM information_schema.columns WHERE table_schema = 'public' AND table_name = 'users' """ ) cols = {} for name, is_nullable, default, data_type in cur.fetchall(): cols[name] = { "nullable": is_nullable == "YES", "default": default, "type": data_type, } return cols def upsert_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]) seeder_user = os.environ["SEEDER_USER"] bot_user = os.environ["BOT_USER"] server = "live.bstein.dev" seeder_id = f"@{seeder_user}:{server}" bot_id = f"@{bot_user}:{server}" conn = psycopg2.connect( host=os.environ["PGHOST"], port=int(os.environ["PGPORT"]), dbname=os.environ["PGDATABASE"], user=os.environ["PGUSER"], password=os.environ["PGPASSWORD"], ) try: with conn: with conn.cursor() as cur: cols = get_cols(cur) upsert_user(cur, cols, seeder_id, os.environ["SEEDER_PASS"], True) upsert_user(cur, cols, bot_id, os.environ["BOT_PASS"], False) finally: conn.close() PY volumeMounts: - name: vault-scripts mountPath: /vault/scripts readOnly: true volumes: - name: vault-scripts configMap: name: comms-vault-env defaultMode: 0555