diff --git a/README.md b/README.md index c9dc8c4..62e3529 100644 --- a/README.md +++ b/README.md @@ -1197,6 +1197,43 @@ neu anlegt. **Proxy-Hosts, Weiterleitungen und Zugriffslisten sind damit weg** – die Zertifikate bleiben. Das Kommando zeigt vorher genau das an und fragt nach. Die Proxy-Hosts lassen sich mit `proxy add` in einem Aufruf neu anlegen. +### 10.1.1 Wenn die Anmeldung fehlschlägt + +Die Meldung nennt inzwischen selbst, woran es liegt – sie zeigt den HTTP-Code, +die Antwort der Schnittstelle und, falls gar nichts antwortete, was curl +gemeldet hat: + +``` +[FEHLER] Anmeldung am Proxy Manager fehlgeschlagen. + Aufgerufen : http://127.0.0.1:81/api/tokens + Konto : admin@example.com + HTTP-Code : 400 + Antwort : Invalid email or password + + Woran es liegen kann + Der Proxy Manager hat geantwortet und die Anmeldung abgelehnt. + Der Weg dorthin stimmt also - Port, Netz und Proxy sind in Ordnung. +``` + +Das ist die halbe Miete: **hat es geantwortet, liegt es nicht am Netz.** +Die andere Richtung sieht so aus: + +| HTTP-Code | Bedeutung | Nächster Schritt | +|---|---|---| +| `400`/`401` | Der Proxy Manager lehnt ab | Konto/Kennwort in der `.env`, oder das Konto gibt es nicht → `npm-reset` | +| `000` | gar keine Antwort | Container aus? Port frei? – der Befehl prüft beides und sagt, welches zutrifft | +| `5xx` + HTML | etwas anderes antwortet | meist der HTTP-Proxy; die erste Zeile der HTML-Antwort wird mit angezeigt | + +Antwortet HTML statt JSON, steht es ausdrücklich da – samt erster Zeile, an der +man erkennt, wer da geantwortet hat: + +``` + Die Antwort ist HTML, kein JSON - sie stammt also nicht von der + Schnittstelle des Proxy Managers, sondern von etwas davor + (HTTP-Proxy, anderer Dienst auf dem Port). Erste Zeile: + 502 Proxy Error... +``` + ### 10.2 Proxy-Host anlegen – ohne Browser Die Weboberfläche lässt sich im Terminal-Browser nur mühsam bedienen; Formulare diff --git a/README_en.md b/README_en.md index a54ee3d..e6271d4 100644 --- a/README_en.md +++ b/README_en.md @@ -1196,6 +1196,42 @@ the account from `NPM_ADMIN_EMAIL`/`NPM_ADMIN_PASSWORD` on the next `up`. remain. The command shows exactly that beforehand and asks for confirmation. The proxy hosts can be recreated with `proxy add` in a single call. +### 10.1.1 When the login fails + +The message now names the cause itself – it shows the HTTP code, the API's +reply and, if nothing answered at all, what curl reported: + +``` +[FEHLER] Anmeldung am Proxy Manager fehlgeschlagen. + Aufgerufen : http://127.0.0.1:81/api/tokens + Konto : admin@example.com + HTTP-Code : 400 + Antwort : Invalid email or password + + Woran es liegen kann + Der Proxy Manager hat geantwortet und die Anmeldung abgelehnt. + Der Weg dorthin stimmt also - Port, Netz und Proxy sind in Ordnung. +``` + +That is half the battle: **if it answered, the network is not the problem.** +The other direction looks like this: + +| HTTP code | meaning | next step | +|---|---|---| +| `400`/`401` | the Proxy Manager refuses | account/password in `.env`, or the account does not exist → `npm-reset` | +| `000` | no answer at all | container down? port free? – the command checks both and says which applies | +| `5xx` + HTML | something else answered | usually the HTTP proxy; the first line of the HTML reply is shown | + +If HTML arrives instead of JSON, it says so explicitly – including the first +line, which reveals who answered: + +``` + Die Antwort ist HTML, kein JSON - sie stammt also nicht von der + Schnittstelle des Proxy Managers, sondern von etwas davor + (HTTP-Proxy, anderer Dienst auf dem Port). Erste Zeile: + 502 Proxy Error... +``` + ### 10.2 Creating a proxy host – without a browser The web interface is painful in a terminal browser, and forms with file uploads diff --git a/scripts/cmk-manage.sh b/scripts/cmk-manage.sh index cf99fb5..717dd4d 100755 --- a/scripts/cmk-manage.sh +++ b/scripts/cmk-manage.sh @@ -3769,31 +3769,135 @@ EOF fi return 1 fi - local body - body="$(curl -sS --max-time 20 --noproxy '*' -X POST "$base/api/tokens" \ + # Antwort, HTTP-Code und curls eigene Fehlermeldung getrennt + # einsammeln - ohne die drei laesst sich hinterher nicht sagen, WORAN + # es lag, und genau das ist hier der haeufigste Zeitfresser. + local body code cerr rc=0 + cerr="$(mktemp)" + body="$(curl -sS --max-time 20 --noproxy '*' -w '\n%{http_code}' \ + -X POST "$base/api/tokens" \ -H 'Content-Type: application/json' \ - -d "{\"identity\":\"$NPM_ADMIN_EMAIL\",\"secret\":\"$NPM_ADMIN_PASSWORD\"}" 2>/dev/null)" || true + -d "{\"identity\":\"$NPM_ADMIN_EMAIL\",\"secret\":\"$NPM_ADMIN_PASSWORD\"}" \ + 2>"$cerr")" || rc=$? + code="${body##*$'\n'}"; body="${body%$'\n'*}" + case "$code" in ''|*[!0-9]*) code=000 ;; esac + local tok; tok="$(json_str "$body" token)" - if [ -z "$tok" ]; then - err "Anmeldung am Proxy Manager fehlgeschlagen." - local m; m="$(json_str "$body" message)" - if [ -n "$m" ]; then printf ' Antwort: %s\n' "$m" >&2; fi - printf ' Geprueft wurde: %s\n' "$base/api/tokens" >&2 - # In Kundennetzen mit Zwangsproxy ist das die haeufigste Ursache - # fuer eine Fehlermeldung, die nach einem API-Problem aussieht. - if [ -n "${http_proxy:-}${HTTP_PROXY:-}${https_proxy:-}${HTTPS_PROXY:-}" ]; then - printf ' - In dieser Umgebung steht ein HTTP-Proxy. Nimmt no_proxy die lokalen - Adressen nicht aus, geht selbst diese Anfrage an ihn - dann meldet - er den Fehler, nicht der Proxy Manager. Nachsehen mit: - %s noproxy -' "$SELF" >&2 - fi - return 1 + if [ -n "$tok" ]; then + rm -f "$cerr" + printf '%s' "$tok" + return 0 fi - printf '%s' "$tok" + + err "Anmeldung am Proxy Manager fehlgeschlagen." + printf ' Aufgerufen : %s\n' "$base/api/tokens" >&2 + printf ' Konto : %s\n' "${NPM_ADMIN_EMAIL:-}" >&2 + printf ' HTTP-Code : %s\n' "$code" >&2 + local cmsg; cmsg="$(sed -n '1p' "$cerr" 2>/dev/null)" + if [ -n "$cmsg" ]; then printf ' curl sagt : %s\n' "$cmsg" >&2; fi + rm -f "$cerr" + # Der Proxy Manager verpackt seine Meldung in "error" - sie ist die + # nuetzlichste Zeile ueberhaupt und gehoert nach oben, nicht ans Ende. + local m; m="$(json_str "$body" message)" + if [ -n "$m" ]; then printf ' Antwort : %s\n' "$m" >&2; fi + + printf '\n %sWoran es liegen kann%s\n' "$C_BLD" "$C_RST" >&2 + + case "$code" in + 400|401|403) + # Es hat geantwortet - der Weg stimmt also, nur die Daten nicht. + printf ' Der Proxy Manager hat geantwortet und die Anmeldung abgelehnt. + Der Weg dorthin stimmt also - Port, Netz und Proxy sind in Ordnung.\n' >&2 + case "$m" in + *"fewer than"*|*"must NOT"*|*"required"*) + printf ' + Die Anfrage war unvollstaendig - meist ein leerer Wert in der .env: + NPM_ADMIN_EMAIL = %s + NPM_ADMIN_PASSWORD = %s + Setzen mit: %s config set NPM_ADMIN_PASSWORD \n' \ + "${NPM_ADMIN_EMAIL:-}" \ + "$([ -n "${NPM_ADMIN_PASSWORD:-}" ] && echo '' || echo '')" \ + "$SELF" >&2 ;; + *) + printf ' + Konto oder Kennwort stimmt nicht. Beide stehen in der .env: + %s config set NPM_ADMIN_EMAIL + %s config set NPM_ADMIN_PASSWORD + + Gibt es das Konto ueberhaupt? Seit Version 2.15 legt der Proxy + Manager keine Standardzugangsdaten an; das Konto entsteht nur beim + ERSTEN Start mit leerer Datenbank aus NPM_ADMIN_EMAIL/-PASSWORD. + War die Datenbank damals schon da, wurde es nie angelegt: + %s npm-reset (Datenbank beiseite, Konto entsteht neu) + Oder von Hand in der Oberflaeche: %s browser\n' \ + "$SELF" "$SELF" "$SELF" "$SELF" >&2 ;; + esac + ;; + 000) + printf ' Es kam ueberhaupt keine HTTP-Antwort.\n' >&2 + # Der Reihe nach das Naheliegende pruefen und BENENNEN + if ! npm_enabled; then + printf ' -> NPM_ENABLED=off - der Proxy Manager soll gar nicht laufen. + Einschalten: %s npm-enable on\n' "$SELF" >&2 + elif ! container_running "$NPM_CONTAINER_NAME"; then + printf ' -> Der Container "%s" laeuft nicht. + Starten: %s up\n' "$NPM_CONTAINER_NAME" "$SELF" >&2 + elif ! port_in_use "${NPM_ADMIN_PORT:-81}"; then + printf ' -> Auf Port %s lauscht nichts. + Der Container laeuft, aber die Oberflaeche ist dort nicht zu + erreichen. Nachsehen: %s logs + Port pruefen/aendern: %s npm-port\n' \ + "${NPM_ADMIN_PORT:-81}" "$SELF" "$SELF" >&2 + else + printf ' -> Port %s ist belegt, antwortet aber nicht auf diese Anfrage. + Vielleicht startet der Dienst noch: %s proxy restart\n' \ + "${NPM_ADMIN_PORT:-81}" "$SELF" >&2 + fi + case "$cmsg" in + *proxy*|*Proxy*) + printf ' -> curl nennt einen Proxy. Pruefen: %s noproxy\n' "$SELF" >&2 ;; + esac + ;; + 5??) + printf ' Es hat etwas geantwortet, aber mit einem Serverfehler. + Kommt die Antwort ueberhaupt vom Proxy Manager? Ein + HTTP-Proxy im Netz antwortet an dieser Stelle gern selbst: + %s noproxy\n' "$SELF" >&2 + ;; + *) + printf ' Unerwartete Antwort - erwartet wurde ein Feld "token".\n' >&2 + ;; + esac + + # Sieht die Antwort nach einer Webseite aus, kommt sie nicht von der + # Schnittstelle - das ist das sicherste Zeichen fuer einen Proxy + # oder einen fremden Dienst auf dem Port. + case "$body" in + '<'*|*'&2 ;; + '') + : ;; + *) + if [ -z "$m" ]; then + printf '\n Antwort (gekuerzt): %s\n' "$(printf '%s' "$body" | tr -d '\n' | cut -c1-120)" >&2 + fi ;; + esac + + if [ -n "${http_proxy:-}${https_proxy:-}${HTTPS_PROXY:-}" ]; then + printf ' + In dieser Umgebung steht ein HTTP-Proxy. Die eigenen Aufrufe gehen + zwar mit "--noproxy" daran vorbei, eigene Tests aber nicht: + %s noproxy\n' "$SELF" >&2 + fi + printf '\n' >&2 + return 1 } + + # npm_api METHODE PFAD [JSON] -> Antwort auf stdout, HTTP-Code via npm_code NPM_CODE_FILE="${TMPDIR:-/tmp}/.cmk-manage-npmcode.$$" trap 'rm -f "$NPM_CODE_FILE"' EXIT diff --git a/scripts/lib/common.sh b/scripts/lib/common.sh index a859d81..b7e478b 100644 --- a/scripts/lib/common.sh +++ b/scripts/lib/common.sh @@ -148,8 +148,13 @@ npm_enabled() { esac } -container_exists() { $RUNTIME container inspect "$1" >/dev/null 2>&1; } -container_running() { [ "$($RUNTIME container inspect -f '{{.State.Running}}' "$1" 2>/dev/null)" = "true" ]; } +# Ohne erkannte Runtime laesst sich nichts sagen - dann schlicht "nein" +# statt unter "set -u" mitten in einer Fehlerdiagnose abzubrechen. +container_exists() { [ -n "${RUNTIME:-}" ] && $RUNTIME container inspect "$1" >/dev/null 2>&1; } +container_running() { + [ -n "${RUNTIME:-}" ] || return 1 + [ "$($RUNTIME container inspect -f '{{.State.Running}}' "$1" 2>/dev/null)" = "true" ] +} require_cmk_running() { container_exists "$CMK_CONTAINER_NAME" \