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>
This commit is contained in:
parent
5404c947d8
commit
2bbe12299f
6 changed files with 114 additions and 17 deletions
39
CHANGELOG.md
39
CHANGELOG.md
|
|
@ -1,5 +1,44 @@
|
|||
# CHANGELOG — Set-OPS
|
||||
|
||||
## 2026-09-29 (29) — `passerelle` fait le trajet d'un visiteur jusqu'à la page de connexion ; fin de la revue des sondes
|
||||
|
||||
Cinquième et dernière des sondes « répond » de la revue (25).
|
||||
|
||||
**Avant.** `check_http` sur `/ping` : vert tant que le processus oauth2-proxy vit, même
|
||||
quand plus personne ne peut entrer — client supprimé ou renommé dans Keycloak, URL de
|
||||
retour retirée du client, IdP injoignable depuis la machine de la passerelle.
|
||||
|
||||
**Maintenant.** Après `/ping`, la sonde fait le trajet d'un visiteur : `/oauth2/start` doit
|
||||
renvoyer vers l'émetteur configuré (lu dans la configuration déployée), pour CE client ; puis
|
||||
l'IdP, joint depuis cette machine avec le même magasin de confiance que la passerelle, doit
|
||||
servir sa page de connexion (200). C'est aussi le chemin de l'échange du code au retour.
|
||||
Un refus de Keycloak est nommé (`Invalid parameter: redirect_uri`, `Client not found`…) ;
|
||||
un IdP injoignable rend le code d'erreur de curl.
|
||||
|
||||
**Ce qu'elle ne teste pas : le secret du client.** Le vérifier demande un échange de jeton
|
||||
raté, que Keycloak écrit dans le journal de sécurité du realm — toutes les 15 minutes, par
|
||||
passerelle, ce serait noyer le journal où l'on cherche les vraies tentatives. Le cas sain
|
||||
n'y écrit rien.
|
||||
|
||||
**Éprouvé.** Au vert sur les quatre passerelles (vigie et console, chez les deux
|
||||
locataires), 35 ms ; le site n'en a pas. Mises en défaut chez Chezlepro : URL de retour non
|
||||
autorisée (`serveur_oauth2_proxy_sonde_retour`) → 400 nommé ; configuration illisible ; port
|
||||
fermé ; magasin de confiance inutilisable → « n'atteint pas l'IdP (curl 77) ». Toutes
|
||||
critiques. **À savoir en lisant le journal du realm `chezlepro`** : ces épreuves y ont laissé
|
||||
cinq `LOGIN_ERROR` (`redirect_uri` vers `exemple.invalid`), les 28 et 29 septembre.
|
||||
|
||||
**Au passage.** Le port de la sonde était écrit en dur (4180) : il dérive de l'écoute. Un
|
||||
échec de `/ping` sortait sur deux lignes : une seule. Et l'archive oauth2-proxy repartait du
|
||||
contrôleur à chaque déploiement, pour la même raison que Keycloak en (26) — le repère était
|
||||
dans `/tmp` ; c'est désormais le binaire installé. Plus aucun rôle ne prend `/tmp` pour
|
||||
repère. Limite qui demeure, dans les deux rôles : un changement de VERSION ne réinstalle pas
|
||||
(l'extraction s'arrête sur `creates`) ; à traiter le jour d'une montée de version.
|
||||
|
||||
**Bilan de la revue.** Les cinq sondes qui disaient « répond » disent désormais « sert » :
|
||||
`filtrage` (GTUBE analysé), `edge` (chaque exposition servie), `identite` (Keycloak
|
||||
authentifié auprès de l'annuaire), `vigie` (base, annuaire ou comptes, Redis), `passerelle`
|
||||
(trajet jusqu'à la connexion).
|
||||
|
||||
## 2026-09-28 (28) — `vigie` vérifie ce que la vigie lit, pas seulement qu'elle répond
|
||||
|
||||
Quatrième des cinq sondes « répond » de la revue (25).
|
||||
|
|
|
|||
|
|
@ -69,3 +69,13 @@ serveur_oauth2_proxy_cache_local: "{{ setops_cache_artefacts | default(lookup('e
|
|||
# CRITIQUE sans rien casser, ce qui rend la seconde preuve REJOUABLE. Une sonde se prouve
|
||||
# deux fois — verte sur le sain, rouge sur le casse.
|
||||
serveur_oauth2_proxy_sonde_attendu: "OK"
|
||||
|
||||
# LE PORT QUE LA SONDE INTERROGE, DERIVE DE L'ECOUTE (2026-09-28). Il etait ecrit en dur
|
||||
# (4180) dans le gabarit : une passerelle deplacee aurait fait crier une sonde saine.
|
||||
serveur_oauth2_proxy_sonde_port: "{{ serveur_oauth2_proxy_ecoute.split(':') | last }}"
|
||||
|
||||
# L'URL DE RETOUR QUE LA SONDE PRESENTE A KEYCLOAK. Vide = celle que la passerelle envoie
|
||||
# vraiment (le cas normal). Mise en defaut PAR PARAMETRE de la seconde etape : une URL que
|
||||
# le client n'autorise pas — Keycloak refuse (400), comme il refuserait tout le monde.
|
||||
# Chaque mise en defaut laisse UNE erreur dans le journal du realm ; le cas sain, aucune.
|
||||
serveur_oauth2_proxy_sonde_retour: ""
|
||||
|
|
|
|||
|
|
@ -15,6 +15,6 @@
|
|||
sondes:
|
||||
- nom: passerelle
|
||||
ttl: 5400
|
||||
raison: 'La passerelle d''authentification repond-elle ? Elle porte l''acces aux applications sans
|
||||
SSO natif — la supervision la premiere. Quand elle meurt, les services derriere restent
|
||||
raison: 'La passerelle d''authentification repond-elle, et mene-t-elle vraiment a la page de connexion
|
||||
de l''IdP pour son client ? Elle porte l''acces aux applications sans SSO natif — la vigie, la console. Quand elle meurt, les services derriere restent
|
||||
debout et deviennent injoignables : on cherche la panne du mauvais cote.'
|
||||
|
|
|
|||
|
|
@ -58,9 +58,14 @@
|
|||
# Sans garde, `get_url` recontacte le serveur distant a CHAQUE deploiement — et un
|
||||
# serveur tiers lent suffit alors a faire tomber un deploiement de flotte. Constate le
|
||||
# 2026-08-09 sur le binaire Forgejo, meme motif ici.
|
||||
#
|
||||
# LE REPERE EST LE BINAIRE INSTALLE, PAS L'ARCHIVE (2026-09-28). On regardait l'archive
|
||||
# dans /tmp : /tmp se vide, et elle repartait du controleur a chaque deploiement (`changed`
|
||||
# sans raison). Le binaire est exactement ce que l'extraction attend (`creates`) : present,
|
||||
# il n'y a rien a apporter. Meme correction que `serveur_keycloak`.
|
||||
- name: L artefact de cette version est-il deja pose ?
|
||||
ansible.builtin.stat:
|
||||
path: "/tmp/oauth2-proxy-{{ serveur_oauth2_proxy_version }}.tar.gz"
|
||||
path: "{{ serveur_oauth2_proxy_binaire }}"
|
||||
register: serveur_oauth2_proxy_archive_present
|
||||
|
||||
# Le controleur telecharge, puis pousse par SSH — la cible ne tire jamais d'Internet.
|
||||
|
|
|
|||
|
|
@ -1,20 +1,63 @@
|
|||
#!/bin/bash
|
||||
# GENERE par Set-OPS (role serveur_oauth2_proxy). Ne pas editer a la main.
|
||||
#
|
||||
# SONDE « passerelle » — La passerelle d'authentification repond-elle ?
|
||||
#
|
||||
# UNE ENVELOPPE, PAS UNE SONDE ECRITE A LA MAIN. `check_http` vient de
|
||||
# `monitoring-plugins` : il parle deja l'API des greffons Nagios, gere les delais, les
|
||||
# redirections et vingt ans de cas limites. On lui passe l'adresse et ce qu'on attend, et
|
||||
# on rend SON code de sortie tel quel. Ecrire du shell ici serait se donner du code a
|
||||
# maintenir et se priver de tout ca — voir docs/supervision-conception.md.
|
||||
# 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 supervision la premiere. Quand elle meurt, les services
|
||||
# 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` (chaine introuvable).
|
||||
exec /usr/lib/nagios/plugins/check_http \
|
||||
-H 127.0.0.1 -p 4180 -u '/ping' \
|
||||
-s '{{ serveur_oauth2_proxy_sonde_attendu }}' \
|
||||
-t 8
|
||||
# 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} »."
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ graph LR
|
|||
|
||||
| sonde | TTL | ce qu'elle voit |
|
||||
|---|---|---|
|
||||
| `passerelle` | 5400 s | La passerelle d'authentification repond-elle ? Elle porte l'acces aux applications sans SSO natif — la supervision la premiere. Quand elle meurt, les services derriere restent debout et deviennent injoignables : on cherche la panne du mauvais cote. |
|
||||
| `passerelle` | 5400 s | La passerelle d'authentification repond-elle, et mene-t-elle vraiment a la page de connexion de l'IdP pour son client ? Elle porte l'acces aux applications sans SSO natif — la vigie, la console. Quand elle meurt, les services derriere restent debout et deviennent injoignables : on cherche la panne du mauvais cote. |
|
||||
|
||||
## Ce qu'il expose en séries
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue