Le GUI n a aucune authentification : GET / sert la page a qui la demande, jeton ecrit dedans, et POST /api exige ce jeton que la page vient de donner. Le jeton garde contre le CSRF, pas contre un visiteur — la seule serrure est --hote 127.0.0.1. Ce qu il offre a qui entre : deployer, creer, raser, editer le plan. La fabric entiere. Le service reste donc sur la boucle locale. Ce qui est publie est un nginx local qui authentifie d abord : oidc par defaut (oauth2-proxy, donc un groupe d annuaire qu on revoque sans deploiement), locale en repli pour un ecosysteme sans annuaire. L authentification est posee au niveau du server, pas d un location. La sonde console-ops mesure une SERRURE : une requete anonyme doit etre REFUSEE. Un 200 y est la pire des reponses, et il ne fait echouer personne. P54 a attrape une contrainte ratee : serveur_ops est insemine par le SITE, qui ne detient pas la voute du locataire. Le role ne nomme donc aucune voute — il declare un parametre, et la couche qui detient le secret le remplit. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
60 lines
2.6 KiB
Django/Jinja
60 lines
2.6 KiB
Django/Jinja
#!/bin/bash
|
|
# GENERE par Set-OPS (role serveur_ops). Ne pas editer a la main.
|
|
#
|
|
# SONDE « console-ops » — la console repond-elle, et son vestibule tient-il ?
|
|
#
|
|
# PAS UNE ENVELOPPE DE GREFFON, ET C'EST ASSUME. `check_http` sait dire « ce service
|
|
# repond ». La verite d'ici est l'inverse : « ce service REFUSE-t-il encore ceux qui
|
|
# n'ont pas de quoi entrer ». Aucun greffon standard ne pense a mesurer une serrure.
|
|
set -uo pipefail
|
|
|
|
GUI={{ serveur_ops_gui_ecoute }}:{{ serveur_ops_gui_port }}
|
|
VESTIBULE=127.0.0.1:{{ serveur_ops_gui_port_public }}
|
|
NOM='{{ serveur_ops_hostname }}'
|
|
MODE='{{ serveur_ops_gui_auth }}'
|
|
|
|
# 1. LE GUI VIT-IL ? On frappe la boucle locale, la ou il est le seul a pouvoir repondre.
|
|
code=$(curl -s -o /dev/null -w '%{http_code}' --max-time 10 "http://${GUI}/" 2>/dev/null)
|
|
if [[ "${code}" != "200" ]]; then
|
|
echo "La console ne repond pas sur ${GUI} (HTTP ${code:-aucune reponse}) — plus personne ne pilote cet ecosysteme depuis le navigateur."
|
|
exit 2
|
|
fi
|
|
|
|
# 2. LE VESTIBULE REFUSE-T-IL ? On frappe SANS justificatif, avec le bon `Host` : c'est
|
|
# ainsi que nginx choisit son vhost, et sans cet en-tete on mesurerait le serveur par
|
|
# defaut — c'est-a-dire autre chose.
|
|
#
|
|
# UN 200 ICI EST LA PIRE DES REPONSES. Il veut dire que le vestibule laisse entrer : la
|
|
# console est alors ouverte a quiconque atteint l'adresse, avec `deployer`, `creer` et
|
|
# l'edition du plan. On le traite comme une panne, parce que c'en est une.
|
|
vu=$(curl -s -o /dev/null -w '%{http_code}' --max-time 10 \
|
|
-H "Host: ${NOM}" "http://${VESTIBULE}/" 2>/dev/null)
|
|
case "${vu}" in
|
|
401|403)
|
|
echo "Console vivante, vestibule (${MODE}) en place : une requete anonyme rend HTTP ${vu}."
|
|
exit 0
|
|
;;
|
|
30[12478])
|
|
# Une passerelle SSO renvoie vers son fournisseur d'identite : c'est un refus, dit
|
|
# autrement. On l'accepte seulement quand c'est le mode declare — en `locale`, une
|
|
# redirection signifierait que le `auth_basic` n'est plus applique.
|
|
if [[ "${MODE}" != "locale" ]]; then
|
|
echo "Console vivante, vestibule (${MODE}) en place : une requete anonyme est renvoyee (HTTP ${vu})."
|
|
exit 0
|
|
fi
|
|
echo "LE VESTIBULE NE DEMANDE PLUS RIEN : en mode locale, une requete anonyme devrait rendre 401, elle rend ${vu}."
|
|
exit 2
|
|
;;
|
|
200)
|
|
echo "LE VESTIBULE EST OUVERT : une requete anonyme obtient la console (HTTP 200). Deployer, creer et raser sont a la portee de qui trouve l'adresse."
|
|
exit 2
|
|
;;
|
|
"" | 000)
|
|
echo "Le vestibule ne repond pas sur ${VESTIBULE} — la console vit, mais l'edge ne peut plus l'atteindre."
|
|
exit 2
|
|
;;
|
|
*)
|
|
echo "Reponse inattendue du vestibule : HTTP ${vu}."
|
|
exit 1
|
|
;;
|
|
esac
|