#!/bin/bash # GENERE par Set-OPS (role serveur_oauth2_proxy). Ne pas editer a la main. # # SONDE « passerelle » — la passerelle repond, et MENE VRAIMENT a la connexion. # # CE QUI TOMBE AVEC ELLE N'EST PAS ELLE. Cette passerelle porte l'acces aux applications # qui n'ont pas de SSO natif — la vigie, la console. Quand elle meurt, les services # derriere restent debout et deviennent injoignables : on cherche la panne du mauvais cote. # # Mise en defaut PAR PARAMETRE : `serveur_oauth2_proxy_sonde_attendu` (premiere etape), # `serveur_oauth2_proxy_sonde_retour` (URL de retour que le client n'autorise pas). set -uo pipefail PORT={{ serveur_oauth2_proxy_sonde_port }} CFG={{ serveur_oauth2_proxy_config }} RETOUR='{{ serveur_oauth2_proxy_sonde_retour }}' # PREMIERE ETAPE — LE PROCESSUS REPOND. `check_http` parle deja l'API des greffons Nagios. ping=$(/usr/lib/nagios/plugins/check_http -H 127.0.0.1 -p "${PORT}" -u '/ping' \ -s '{{ serveur_oauth2_proxy_sonde_attendu }}' -t 8 2>&1) rc=$? (( rc == 0 )) || { echo "La passerelle ne repond pas : $(printf '%s' "${ping}" | tr '\n' ' ' | cut -c1-160)"; exit "${rc}"; } # SECONDE ETAPE — ELLE MENE A LA CONNEXION (2026-09-28). `/ping` repond tant que le # processus vit, meme quand plus personne ne peut entrer : client supprime ou renomme # dans Keycloak, URL de retour retiree du client, IdP injoignable DEPUIS CETTE MACHINE # (resolution, route, pare-feu, autorite de certification). On fait donc le trajet d'un # visiteur : `/oauth2/start` doit renvoyer vers l'IdP configure, pour CE client ; et # l'IdP, joint d'ici avec le meme magasin de confiance que la passerelle, doit servir sa # page de connexion. C'est le meme chemin que prend l'echange du code apres connexion. # # CE QU'ON NE TESTE PAS, ET POURQUOI : le SECRET du client. Le verifier demande un echange # de jeton rate — Keycloak l'ecrit dans le journal de securite du realm. Toutes les # 15 minutes, par passerelle, ce serait noyer le journal qu'on lit pour trouver les vraies # tentatives. Le cas sain ici n'ecrit RIEN dans ce journal. valeur() { grep -m1 -oP "^$1\s*=\s*\[?\"\K[^\"]+" "${CFG}" 2>/dev/null; } EMETTEUR=$(valeur oidc_issuer_url); CLIENT=$(valeur client_id); CA=$(valeur provider_ca_files) [[ -n "${EMETTEUR}" && -n "${CLIENT}" ]] \ || { echo "La passerelle repond, mais sa configuration est illisible (${CFG})."; exit 2; } loc=$(curl -s -o /dev/null -D - --max-time 8 -H 'X-Forwarded-Proto: https' \ "http://127.0.0.1:${PORT}/oauth2/start?rd=%2F" 2>/dev/null | tr -d '\r' \ | awk 'tolower($1) == "location:" {print $2; exit}') if [[ "${loc}" != "${EMETTEUR}/protocol/openid-connect/auth?"* || "${loc}" != *"client_id=${CLIENT}&"* ]]; then echo "La passerelle repond, mais NE RENVOIE PAS vers ${EMETTEUR} pour le client « ${CLIENT} » (renvoie : ${loc:-rien})." exit 2 fi [[ -n "${RETOUR}" ]] && loc=$(printf '%s' "${loc}" | sed -E "s#redirect_uri=[^&]*#redirect_uri=${RETOUR}#") page=$(mktemp); trap 'rm -f "${page}"' EXIT res=$(curl -s -o "${page}" -w '%{http_code} %{exitcode} %{errormsg}' --max-time 10 \ ${CA:+--cacert "${CA}"} "${loc}" 2>/dev/null) code=${res%% *} if [[ "${code}" == "000" ]]; then echo "La passerelle renvoie vers ${EMETTEUR}, mais cette machine N'ATTEINT PAS l'IdP (curl ${res#* }) — la connexion echouera au retour." exit 2 fi if [[ "${code}" != "200" ]]; then motif=$(grep -oiE 'Invalid parameter: [a-z_]+|Client not found|Realm does not exist|Page not found' "${page}" | head -1) echo "L'IdP REFUSE le trajet de connexion du client « ${CLIENT} » : HTTP ${code}${motif:+ — ${motif}}. Personne ne peut entrer." exit 2 fi echo "Passerelle : repond, et mene a la page de connexion de ${EMETTEUR} pour le client « ${CLIENT} »."