#!/bin/bash # # Registriert den lokalen OPs-Agenten (Rolle "ops", Issue #66) bei der monitor-API und legt # die Zugangsdaten fuer check_fds.sh in monitor-api.conf ab - also genau die beiden Schritte # aus "Weg 3" im README, die sich nicht in hosts.conf/credentials.conf erledigen lassen. # # Aufruf (im Verzeichnis mit docker-compose.yml, die API muss laufen): # # ./register-ops-agent.sh [Anzeigename] # Standard-Anzeigename: "OPs" # # Ueberschreibbar per Umgebungsvariable: MONITOR_API_BASE, MONITOR_ADMIN_API_KEY. # # Wichtig: Den API-Key gibt die API nur bei der Registrierung einmalig heraus - deshalb # ueberschreibt das Skript eine vorhandene monitor-api.conf nicht (--force erzwingt es, # der alte Agent bleibt dann mit seinem Schreibtisch registriert). set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" ENV_FILE="$SCRIPT_DIR/.env" API_CONF="${MONITOR_API_CONF:-$SCRIPT_DIR/monitor-api.conf}" DISPLAY_NAME="OPs" FORCE=0 for arg in "$@"; do case "$arg" in -f|--force) FORCE=1 ;; -h|--help) sed -n '2,20p' "${BASH_SOURCE[0]}" | sed 's/^# \?//'; exit 0 ;; -*) echo "Unbekannte Option: $arg" >&2; exit 1 ;; *) DISPLAY_NAME="$arg" ;; esac done if ! command -v curl >/dev/null 2>&1; then echo "Fehler: curl wird benoetigt." >&2 exit 1 fi # Werte aus der .env lesen, statt sie zu sourcen: die Datei enthaelt Kommentare und Werte, # die als Shell-Code anders bedeuten wuerden, als sie Docker Compose liest. env_value() { [ -f "$ENV_FILE" ] || return 0 sed -n "s/^[[:space:]]*$1=//p" "$ENV_FILE" | tail -n1 \ | sed -e 's/^"\(.*\)"$/\1/' -e "s/^'\(.*\)'\$/\1/" } ADMIN_API_KEY="${MONITOR_ADMIN_API_KEY:-$(env_value MONITOR_ADMIN_API_KEY)}" API_BASE="${MONITOR_API_BASE:-$(env_value MONITOR_API_BASE)}" API_BASE="${API_BASE:-http://localhost:8091}" # In der .env steht die Basis-URL inklusive "/api/v1" (so braucht sie das Frontend), # monitor-api.conf dagegen ohne - check_fds.sh haengt den Pfad selbst an. API_ROOT="${API_BASE%/}" API_ROOT="${API_ROOT%/api/v1}" if [ -z "$ADMIN_API_KEY" ]; then echo "Fehler: MONITOR_ADMIN_API_KEY steht weder in der Umgebung noch in $ENV_FILE." >&2 exit 1 fi if [ "$ADMIN_API_KEY" = "change-me" ]; then echo "Fehler: MONITOR_ADMIN_API_KEY ist noch der Beispielwert 'change-me'." >&2 exit 1 fi json_escape() { printf '%s' "$1" | sed -e 's/\\/\\\\/g' -e 's/"/\\"/g' } # Ein zweiter Agent gleichen Namens wuerde einen weiteren der acht Schreibtische belegen. # GET /api/v1/agents ist unauthentifiziert (API.md "Agenten") und dient hier auch als # Erreichbarkeitspruefung. Wird vor der Existenzpruefung von $API_CONF geholt, weil eine # bestehende, aber noch unmigrierte Datei (Issue #75, siehe unten) die ID aus genau dieser # Antwort nachtraegt, statt den Agenten neu zu registrieren. agents_json=$(curl -sS --max-time 10 "$API_ROOT/api/v1/agents" 2>/dev/null) || { echo "Fehler: API unter $API_ROOT nicht erreichbar. Laeuft 'docker compose up'?" >&2 exit 1 } if [ -e "$API_CONF" ] && [ "$FORCE" -ne 1 ]; then if ! grep -q '^MONITOR_AGENT_ID=' "$API_CONF"; then # Migration (Issue #75): aeltere monitor-api.conf kennen MONITOR_AGENT_ID noch nicht, # ohne das check_fds.sh den Aktivitaets-Endpoint nicht adressieren kann. Die ID laesst # sich hier ohne Neuregistrierung nachtragen - GET /api/v1/agents kennt sie bereits # (Reihenfolge der Felder wie von AgentRepository::hidingKey() geliefert: "id" direkt # vor "display_name"). # "|| true" haengt am Ende der Pipeline: findet keiner der beiden grep-Aufrufe eine # Uebereinstimmung, wuerde ihr Exit-Code mit "set -o pipefail" sonst das ganze Skript # kommentarlos beenden, statt in die Fehlermeldung darunter zu fallen. existing_id=$(printf '%s' "$agents_json" \ | grep -oE "\"id\":[0-9]+,\"display_name\":\"$(json_escape "$DISPLAY_NAME")\"" \ | head -n1 | grep -oE '[0-9]+' || true) if [ -n "$existing_id" ]; then printf 'MONITOR_AGENT_ID="%s"\n' "$existing_id" >> "$API_CONF" echo "MONITOR_AGENT_ID fehlte in $API_CONF und wurde nachgetragen (ID $existing_id)." exit 0 fi fi echo "Fehler: $API_CONF existiert bereits - der bisherige OPs-Agent ist offenbar schon" >&2 echo " registriert. Zum Neuanlegen die Datei wegsichern oder --force angeben." >&2 exit 1 fi if printf '%s' "$agents_json" | grep -q "\"display_name\":\"$(json_escape "$DISPLAY_NAME")\""; then echo "Fehler: Ein Agent namens \"$DISPLAY_NAME\" ist bereits registriert." >&2 echo " Anderen Anzeigenamen uebergeben oder den alten Agenten loeschen." >&2 exit 1 fi response=$(curl -sS -w '\n%{http_code}' --max-time 10 -X POST "$API_ROOT/api/v1/agents" \ -H 'Content-Type: application/json' \ -H "X-Admin-Key: $ADMIN_API_KEY" \ -d "{\"display_name\": \"$(json_escape "$DISPLAY_NAME")\", \"role\": \"ops\"}") http_code=$(printf '%s' "$response" | tail -n1) body=$(printf '%s' "$response" | sed '$d') if [ "$http_code" != "201" ]; then echo "Fehler: Registrierung fehlgeschlagen (HTTP $http_code)." >&2 echo "$body" >&2 exit 1 fi api_key=$(printf '%s' "$body" | grep -oE '"api_key":"[0-9a-f]+"' | head -n1 | cut -d'"' -f4) agent_id=$(printf '%s' "$body" | grep -oE '"id":[0-9]+' | head -n1 | cut -d: -f2) desk_index=$(printf '%s' "$body" | grep -oE '"desk_index":(null|[0-9]+)' | head -n1 | cut -d: -f2) if [ -z "$api_key" ]; then echo "Fehler: Die Antwort enthielt keinen api_key:" >&2 echo "$body" >&2 exit 1 fi # Erst die Rechte setzen, dann schreiben - sonst stuende das Secret kurzzeitig lesbar da. umask 077 cat > "$API_CONF" <> /var/log/check_fds.log 2>&1"