//Cloudogu EcoSystem Docs

PAT-Proxy

Im Teamscale-Dogu nimmt der Go-Proxy HTTP-Anfragen auf Port 8080 entgegen. Der Proxy leitet an einen separaten Teamscale-Adapter über den Unix-Socket /tmp/teamscale-pat/adapter.sock weiter. Teamscale lauscht intern auf 127.0.0.1:8081. Die Setup- und Backup-Aufrufe verwenden diesen internen Port. Auch nach dem Wiederherstellen einer alten Konfiguration werden Port und Bind-Adresse vor dem Teamscale-Start gesetzt. Der externe Dogu-Nginx und der TCP-Healthcheck verwenden weiterhin Port 8080. Die Port- und Bind-Einstellungen stehen in config/teamscale.properties, siehe Teamscale-Dokumentation.

Für /teamscale/api und /teamscale/api/… gilt:

  1. Bei Basic Auth und einem Passwort mit dem Präfix pat_ sendet der Proxy einen GET-Request mit dem ursprünglichen Authorization-Header an https://<fqdn>/cas/api/pats/validate?scope=/teamscale. Den FQDN liest das Startskript mit doguctl config --global fqdn aus.
  2. Nur HTTP 200 gilt als erfolgreiche Validierung. Erst danach übergibt der Proxy die validierte Identität an den Adapter. Dort liest der Go-Adapter über doguctl config -e das Ersatzpasswort unter pat/storedkey/<username> aus. Für den Schlüssel wird jedes Zeichen außerhalb von A–Z, a–z, 0–9 und _ durch _ ersetzt, beispielsweise alice@example/team durch alice_example_team. Fehlt der Key, erzeugt und speichert der Adapter ihn über die Teamscale-API. Der Benutzername im Authorization-Header bleibt unverändert. Fehler beim erstmaligen Auslesen oder ein leeres Passwort führen zu HTTP 502 ohne Weiterleitung an Teamscale.
  3. HTTP 400 oder 401 von CAS werden mit demselben Status an den Client beantwortet. Andere Statuscodes, Verbindungsfehler und ein Validierungs-Timeout nach fünf Sekunden führen zu HTTP 502. Diese Anfragen erreichen Teamscale nicht.

Andere Pfade sowie Anfragen ohne Basic Auth oder ohne pat_-Passwort werden ohne CAS-Prüfung weitergeleitet. Pfad, Query, Methode und Body bleiben erhalten; HTTP-Verbindungsheader werden für die jeweilige Verbindung neu verwaltet. Der Proxy protokolliert keine Zugangsdaten und folgt keinen CAS-Redirects. Validierungsergebnisse werden nicht gecacht.

Konfiguration

Das Startskript übergibt die Konfiguration als CLI-Parameter:

fqdn="$(doguctl config --global fqdn)"
/usr/local/bin/pat-proxy --listenAddress 0.0.0.0:8080 \
  --upstreamSocket /tmp/teamscale-pat/adapter.sock --apiPath /teamscale/api \
  --casUrl "https://${fqdn}/cas/api/pats/validate" --scope /teamscale \
  --validationTimeout 5 --validationEnabled=true --casInsecure=true

--casInsecure=true deaktiviert die TLS-Zertifikatsprüfung für die bisherige Testinstallation. Mit passendem Zertifikat --casInsecure=false verwenden. Der Scope wird vom Proxy an die CAS-URL angehängt.

Das gespeicherte Ersatzpasswort muss von Teamscale für den jeweiligen Benutzer akzeptiert werden. Der Prozessbenutzer teamscale benötigt Zugriff auf die entsprechenden doguctl-Konfigurationswerte. Die Passwortabfrage wird nicht gecacht.

Proxy, Adapter und Teamscale laufen als Benutzer teamscale. Beim Ende eines der drei Prozesse werden auch die anderen beendet und der Container beendet sich mit Fehlerstatus. SIGTERM/SIGINT werden an alle drei Prozesse weitergegeben.

Tests

Die Stage Setup im Jenkinsfile aktiviert pat/enabled in CAS über ecoSystem.setup(registryConfig: ...). Sie erzeugt pro Build gemeinsame technische API-Zugangsdaten für CAS und Usermgt und übergibt diese über registryConfigEncrypted unter experimental/totp/api_user_name und experimental/totp/api_user_password. Das Setup schreibt die Werte verschlüsselt, bevor die Dogus starten. Eine TOTP-Aktivierung ist für diese PAT-Tests nicht nötig; Usermgt benötigt für seinen PAT-Endpunkt keinen eigenen pat/enabled-Wert. Die API-Zugangsdaten authentifizieren Usermgt gegenüber CAS; der PAT-Eigentümer wird weiterhin aus der angemeldeten Testuser-Session bestimmt.

Die provisionierten CAS- und Usermgt-Versionen müssen PAT-Unterstützung enthalten. Das Jenkinsfile installiert standardmäßig die veröffentlichten official-Abhängigkeiten; die benachbarten lokalen Repositories werden dadurch nicht automatisch gebaut.

make -C pat-proxy test

Die Adapter-Tests verwenden lokale Teamscale-Testserver und simulierte Konfigurationsablagen; echte PATs oder ein laufendes CAS sind nicht nötig. Sie prüfen unter anderem Erneuerung, einmaligen Retry, Requests mit Body, parallele Erneuerungen und das Logging.

Diagnose bei Bad Gateway

Der Proxy schreibt JSON-Logs nach stderr, sichtbar in den Container-Logs:

docker logs -f <containername>
# Bei Kubernetes:
kubectl logs -f <podname> -c <containername>

Die Anfrageereignisse des Proxys enthalten component: "pat-proxy", requestId, event und elapsedMs. Vom Proxy erzeugte Fehlerantworten enthalten dieselbe ID im Header X-Pat-Proxy-Request-Id. Es werden keine Benutzernamen, Zugangsdaten, Request-URLs, Bodies oder ungefilterten Fehlermeldungen ausgegeben.

Ereignis / Code Bedeutung
cas_validation_ok CAS hat HTTP 200 geliefert; anschließend wird das Ersatzpasswort ausgelesen
cas_validation_rejected CAS-Status steht in casStatus, der Client-Status in responseStatus
cas_validation_error / CAS_TIMEOUT CAS hat innerhalb von fünf Sekunden keine Antwortheader geliefert
cas_validation_error / CAS_CONNECTION_ERROR Verbindung zu CAS fehlgeschlagen, z. B. wegen DNS, Verbindungsablehnung oder TLS
upstream_connection_error Verbindung zum Teamscale-Adapter über den Unix-Socket fehlgeschlagen; Antwort HTTP 502
upstream_response Der Adapter hat HTTP 4xx/5xx geliefert (upstreamStatus); die Antwort kann von Teamscale oder vom Adapter stammen

Der Adapter schreibt ebenfalls JSON-Logs nach stderr, mit component: "teamscale-adapter". Sein Mindestlevel folgt beim Containerstart der Dogu-Einstellung logging/root (Standard WARN), über TEAMSCALE_LOGLEVEL und den expliziten Parameter --logLevel. DEBUG, INFO, WARN und ERROR sind zulässig. Fehler beim Verbindungsaufbau, Key-Zugriff, Erneuern oder Retry verwenden ERROR und bleiben auch bei WARN sichtbar. Erfolgreiche Abläufe verwenden INFO. Der separate PAT-Proxy übernimmt diese Einstellung derzeit nicht. Seine Anfrageereignisse verwenden dieselben Felder, aber eigene Request-IDs. Diese werden nicht mit den Proxy-IDs abgeglichen. upstream_connection_error bezeichnet beim Adapter die Verbindung zu Teamscale auf Port 8081; ein fester Fehlercode grenzt die Ursache ein. Dieses Ereignis beendet den Adapter nicht und kann während des Teamscale-Starts auftreten. upstream_response enthält den endgültigen Teamscale-Status ab HTTP 400. Die Erneuerung wird durch stored_access_key_rejected, access_key_renewed, access_key_renewal_failed, access_key_retry_failed und access_key_retry_skipped sichtbar. Die vollständige Ereignistabelle steht in der Adapter-Dokumentation.

Der Go-Proxy liegt im Image unter /usr/local/bin/pat-proxy. Der Docker-Build lädt das durch PAT_PROXY_VERSION bestimmte Release-Archiv und prüft PAT_PROXY_SHA256SUM. Der Teamscale-Adapter wird in einer eigenen Docker-Build-Stage aus diesem Repository kompiliert. Nach Änderungen das Image neu bauen.

Code-Struktur

  • Eigenständiges Repository cloudogu/pat-proxy: CAS-PAT-Proxy.
  • pat-proxy/: Go-Teamscale-Adapter, gebaut als /usr/local/bin/teamscale-adapter.
  • pat-proxy/store.go: Konfigurationszugriff über externe doguctl config -e-Aufrufe.
  • pat-proxy/accessor.go: Liest gespeicherte Keys oder erzeugt und speichert sie über die Teamscale-API.
  • pat-proxy/renewal.go: Erneuert abgelehnte Keys und wiederholt wiederholbare Anfragen höchstens einmal.

Fehlt der gespeicherte Key (NO_STORED_KEY), liest der Adapter config_admin_username und config_admin_access_key über doguctl config -e. Anschließend erzeugt ein authentifizierter POST an http://127.0.0.1:8081/teamscale/api/users/<username>/access-key einen Access-Key. Die JSON-Antwort wird als Ersatzpasswort gespeichert. Vorhandene Keys werden wiederverwendet; Fehler beim erstmaligen Key-Zugriff führen zu HTTP 502.

Lehnt Teamscale einen gespeicherten Key bei einer validierten PAT-Anfrage mit HTTP 401 ab, erneuert der Adapter den Key über die Admin-Zugangsdaten und überschreibt den gespeicherten Wert. Parallele Erstzugriffe und Erneuerungen sind pro Konfigurationsschlüssel innerhalb des Adapter-Prozesses synchronisiert. Ein inzwischen erneuerter Key wird wiederverwendet. HTTP 403 und Anfragen ohne validierte PAT-Identität lösen keine Erneuerung aus.

Anfragen ohne Body werden höchstens einmal mit dem neuen Key wiederholt. Request-Bodies werden nicht gepuffert: Ohne vorhandene GetBody-Funktion bleibt die aktuelle Antwort HTTP 401, und der neue Key steht beim nächsten Aufruf bereit. Scheitern Erneuerung oder Speicherung, bleibt ebenfalls die ursprüngliche 401-Antwort erhalten. Ein Verbindungsfehler beim Retry liefert 502.

Der Adapter benötigt Go 1.26.8 und das ausführbare doguctl im PATH. Classic- und Multinode-Konfiguration sowie Verschlüsselung übernimmt doguctl. In Multinode muss /var/ces/config für lokal gespeicherte Keys persistent eingebunden sein. Weitere CLI-Optionen stehen in pat-proxy/README.md.

Interne Übergabe und Wiederverwendung

Der Proxy entfernt eingehende Header mit dem Präfix X-Internal-Auth- bei jeder Anfrage. Nach CAS-Erfolg entfernt er den ursprünglichen Authorization-Header und setzt X-Internal-Auth-Method: cas-pat sowie X-Internal-Auth-User mit dem Base64-kodierten ursprünglichen Benutzernamen. Base64 dient nur der sicheren Header-Kodierung. Vertrauen entsteht durch den internen Transport, nicht durch Base64. Der Adapter entfernt diese Metadaten vor der Weiterleitung an Teamscale. Das Socket-Verzeichnis hat Modus 0700, der Socket 0600; Prozesse desselben Systembenutzers gehören damit zur Vertrauensgrenze.

Der eigenständige Proxy enthält keine Teamscale-spezifischen Pfade oder CAS-URL. --apiPath legt den zu prüfenden Pfad einschließlich Unterpfaden fest (Standard /). Bei aktiver Validierung muss --casUrl gesetzt sein. --validationEnabled=false deaktiviert die CAS-Prüfung und erzeugt keine Validierungsmarkierung. --upstreamSocket legt einen internen Unix-Socket fest; alternativ gelten --upstreamHost (Standard 127.0.0.1) und --upstreamPort (Standard 8081). Ein Empfänger validierter Identitäten muss über einen vertrauenswürdigen internen Transport erreichbar sein.

Im Teamscale-Dogu setzt das Startskript Pfad, CAS-URL und Socket-Verbindung. TEAMSCALE_ADAPTER_SOCKET überschreibt den gemeinsamen Socket-Pfad. Der Go-Adapter liest und erzeugt Keys direkt gegen Teamscale auf Port 8081. Der Konfigurationszugriff erfolgt über doguctl-Prozesse; Logs enthalten keine Zugangsdaten.