Set-OPS-Public/roles/serveur_oauth2_proxy/templates/sonde-passerelle.sh.j2
Daniel Allaire 2bbe12299f sonde passerelle : le trajet d un visiteur jusqu a la page de connexion
Apres /ping, /oauth2/start doit renvoyer vers l emetteur configure pour ce client, et
l IdP, joint depuis la passerelle, doit servir sa page de connexion. Le secret du client
n est pas teste (journal du realm). Port derive de l ecoute ; archive oauth2-proxy
plus retransferee a chaque deploiement. Fin de la revue des sondes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 00:30:43 -04:00

63 lines
3.7 KiB
Django/Jinja

#!/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} »."