daef7ea190
Helper functions (matrix-mas capability group): - mas_client_register_bash_infra: register/sync OAuth clients via mas-cli - mas_syn2mas_migration_bash_infra: dry-run + apply user migration to MAS - synapse_msc3861_enable_go_infra: edit homeserver.yaml MSC3861 block (with diff) - wellknown_oidc_patch_go_infra: patch well-known JSON with msc2965.authentication - synapse_login_flows_check_go_infra: health-check post-migration login flows Flows + issues for custom Matrix clients (PC + Android): - 0010 matrix-client-pc: Wails + React+Mantine (issues 0147-0153) - 0011 matrix-client-android: Kotlin + Compose (issues 0154-0161) - 0162 enable MAS as auth provider (Synapse delegate) — EXECUTED on VPS - 0163 custom admin panel propio (sustituye synapse-admin) Production state (organic-machine.com): - Synapse migrated SQLite -> Postgres - MSC3861 active, password_config disabled - 21 users + 41 access_tokens migrated via syn2mas - 4 MAS clients registered (element, matrix_pc, matrix_android, admin_panel) - synapse-admin container removed + Coolify route deleted - well-known patched with org.matrix.msc2965.authentication Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
205 lines
7.8 KiB
Bash
205 lines
7.8 KiB
Bash
#!/usr/bin/env bash
|
|
# mas_client_register — Registra/sincroniza clientes OAuth en Matrix Authentication Service (MAS)
|
|
# via mas-cli config sync ejecutado en container Docker remoto a traves de SSH.
|
|
set -euo pipefail
|
|
|
|
mas_client_register() {
|
|
local ssh_host=""
|
|
local container=""
|
|
local config_file=""
|
|
local dry_run=false
|
|
|
|
# Parse args
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--ssh-host)
|
|
ssh_host="$2"
|
|
shift 2
|
|
;;
|
|
--container)
|
|
container="$2"
|
|
shift 2
|
|
;;
|
|
--config-file)
|
|
config_file="$2"
|
|
shift 2
|
|
;;
|
|
--dry-run)
|
|
dry_run=true
|
|
shift
|
|
;;
|
|
--help|-h)
|
|
cat >&2 <<'USAGE'
|
|
mas_client_register - Sincroniza clientes OAuth en MAS via mas-cli config sync
|
|
|
|
Usage:
|
|
mas_client_register --ssh-host <host> --container <name> --config-file <path> [--dry-run]
|
|
|
|
Options:
|
|
--ssh-host Alias SSH del VPS (ej. organic-machine.com)
|
|
--container Nombre del container MAS (ej. element_matrix_chat-mas-1)
|
|
--config-file Ruta en el VPS al mas/config.yaml (ej. /home/ubuntu/project/mas/config.yaml)
|
|
--dry-run Solo valida config y muestra diff, sin aplicar cambios
|
|
|
|
Output: JSON en stdout con status, applied, clients_total, clients_diff, stderr
|
|
USAGE
|
|
# emit minimal valid JSON so callers that parse stdout don't break
|
|
echo '{"status":"help","applied":false,"clients_total":0,"clients_diff":[],"stderr":""}'
|
|
return 0
|
|
;;
|
|
*)
|
|
echo "mas_client_register: argumento desconocido: $1" >&2
|
|
return 1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
# Validar argumentos obligatorios
|
|
local errors=()
|
|
[[ -z "$ssh_host" ]] && errors+=("--ssh-host es obligatorio")
|
|
[[ -z "$container" ]] && errors+=("--container es obligatorio")
|
|
[[ -z "$config_file" ]] && errors+=("--config-file es obligatorio")
|
|
|
|
if [[ ${#errors[@]} -gt 0 ]]; then
|
|
for err in "${errors[@]}"; do
|
|
echo "ERROR: $err" >&2
|
|
done
|
|
echo '{"status":"error","applied":false,"clients_total":0,"clients_diff":[],"stderr":"missing required arguments"}'
|
|
return 1
|
|
fi
|
|
|
|
# Verificar dependencias locales
|
|
if ! command -v jq &>/dev/null; then
|
|
echo "ERROR: jq no encontrado en el host local. Instalar: apt install jq / brew install jq" >&2
|
|
echo '{"status":"error","applied":false,"clients_total":0,"clients_diff":[],"stderr":"jq not found on local host"}'
|
|
return 1
|
|
fi
|
|
|
|
echo "mas_client_register: ssh-host=$ssh_host container=$container dry-run=$dry_run" >&2
|
|
|
|
# La ruta de config dentro del container siempre es /data/config.yaml (mount convention de MAS)
|
|
local container_config="/data/config.yaml"
|
|
|
|
# ---- PASO 1: Verificar sintaxis YAML con mas-cli config check ----
|
|
echo "mas_client_register: verificando sintaxis de config con mas-cli config check..." >&2
|
|
local check_stdout check_stderr check_exit
|
|
check_stdout=$(ssh "$ssh_host" \
|
|
"docker exec ${container} mas-cli config check --config ${container_config}" 2>/tmp/mas_check_stderr_$$ || true)
|
|
check_exit=$?
|
|
check_stderr=$(cat /tmp/mas_check_stderr_$$ 2>/dev/null || true)
|
|
rm -f /tmp/mas_check_stderr_$$
|
|
|
|
if [[ $check_exit -ne 0 ]]; then
|
|
echo "mas_client_register: config check falló (exit=$check_exit)" >&2
|
|
echo "$check_stderr" >&2
|
|
local escaped_stderr
|
|
escaped_stderr=$(printf '%s' "${check_stderr}" | jq -Rs '.')
|
|
echo "{\"status\":\"error\",\"applied\":false,\"clients_total\":0,\"clients_diff\":[],\"stderr\":${escaped_stderr}}"
|
|
return 1
|
|
fi
|
|
|
|
echo "mas_client_register: config check OK" >&2
|
|
|
|
# ---- PASO 2: dry-run o sync ----
|
|
if [[ "$dry_run" == "true" ]]; then
|
|
# Ejecutar mas-cli config dump para mostrar el estado actual y lo que se aplicaria
|
|
echo "mas_client_register: modo dry-run — ejecutando mas-cli config dump..." >&2
|
|
local dump_stdout dump_stderr dump_exit
|
|
dump_stdout=$(ssh "$ssh_host" \
|
|
"docker exec ${container} mas-cli config dump --config ${container_config}" 2>/tmp/mas_dump_stderr_$$ || true)
|
|
dump_exit=$?
|
|
dump_stderr=$(cat /tmp/mas_dump_stderr_$$ 2>/dev/null || true)
|
|
rm -f /tmp/mas_dump_stderr_$$
|
|
|
|
if [[ $dump_exit -ne 0 ]]; then
|
|
echo "mas_client_register: config dump falló (exit=$dump_exit)" >&2
|
|
echo "$dump_stderr" >&2
|
|
local escaped_stderr
|
|
escaped_stderr=$(printf '%s' "${dump_stderr}" | jq -Rs '.')
|
|
echo "{\"status\":\"error\",\"applied\":false,\"clients_total\":0,\"clients_diff\":[],\"stderr\":${escaped_stderr}}"
|
|
return 1
|
|
fi
|
|
|
|
# Extraer listado de clients del dump (buscar lineas con client_id o type: client)
|
|
local clients_diff_raw
|
|
clients_diff_raw=$(printf '%s\n' "$dump_stdout" | grep -E "client_id:|client_name:" | \
|
|
sed 's/^[[:space:]]*//' | head -50 || true)
|
|
|
|
local diff_json
|
|
diff_json=$(printf '%s\n' "$dump_stdout" | jq -Rs 'split("\n") | map(select(length > 0)) | map(ltrimstr(" "))' 2>/dev/null \
|
|
|| echo '["(jq parse error — ver stderr)"]')
|
|
|
|
local escaped_dump_stderr
|
|
escaped_dump_stderr=$(printf '%s' "${dump_stderr}" | jq -Rs '.')
|
|
|
|
echo "mas_client_register: dry-run completado. dump lines=$(echo "$dump_stdout" | wc -l)" >&2
|
|
|
|
jq -n \
|
|
--argjson diff "$diff_json" \
|
|
--argjson stderr_str "$escaped_dump_stderr" \
|
|
'{
|
|
status: "dry-run",
|
|
applied: false,
|
|
clients_total: ($diff | length),
|
|
clients_diff: $diff,
|
|
stderr: $stderr_str
|
|
}'
|
|
return 0
|
|
fi
|
|
|
|
# ---- PASO 3: sync real ----
|
|
echo "mas_client_register: ejecutando mas-cli config sync --prune..." >&2
|
|
local sync_stdout sync_stderr sync_exit
|
|
sync_stdout=$(ssh "$ssh_host" \
|
|
"docker exec ${container} mas-cli config sync --config ${container_config} --prune" \
|
|
2>/tmp/mas_sync_stderr_$$ || true)
|
|
sync_exit=$?
|
|
sync_stderr=$(cat /tmp/mas_sync_stderr_$$ 2>/dev/null || true)
|
|
rm -f /tmp/mas_sync_stderr_$$
|
|
|
|
echo "mas_client_register: sync exit=$sync_exit" >&2
|
|
if [[ -n "$sync_stderr" ]]; then
|
|
echo "mas_client_register stderr: $sync_stderr" >&2
|
|
fi
|
|
|
|
if [[ $sync_exit -ne 0 ]]; then
|
|
local escaped_stderr
|
|
escaped_stderr=$(printf '%s' "${sync_stderr}" | jq -Rs '.')
|
|
echo "{\"status\":\"error\",\"applied\":false,\"clients_total\":0,\"clients_diff\":[],\"stderr\":${escaped_stderr}}"
|
|
return 1
|
|
fi
|
|
|
|
# Parsear output del sync para extraer lineas con cambios aplicados
|
|
local diff_lines
|
|
diff_lines=$(printf '%s\n' "$sync_stdout" | grep -E "^\s*(created|updated|deleted|unchanged|synced)" || true)
|
|
|
|
local diff_json
|
|
diff_json=$(printf '%s\n' "$sync_stdout" | jq -Rs 'split("\n") | map(select(length > 0))' 2>/dev/null \
|
|
|| echo '[]')
|
|
|
|
local clients_count
|
|
clients_count=$(printf '%s\n' "$sync_stdout" | grep -cE "client" 2>/dev/null || echo 0)
|
|
|
|
local escaped_sync_stderr
|
|
escaped_sync_stderr=$(printf '%s' "${sync_stderr}" | jq -Rs '.')
|
|
|
|
echo "mas_client_register: sync completado con exito" >&2
|
|
|
|
jq -n \
|
|
--argjson diff "$diff_json" \
|
|
--argjson total "$clients_count" \
|
|
--argjson stderr_str "$escaped_sync_stderr" \
|
|
'{
|
|
status: "ok",
|
|
applied: true,
|
|
clients_total: $total,
|
|
clients_diff: $diff,
|
|
stderr: $stderr_str
|
|
}'
|
|
}
|
|
|
|
# Ejecutar si se llama directamente (no sourced)
|
|
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
|
mas_client_register "$@"
|
|
fi
|