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
48 lines
2.3 KiB
Django/Jinja
48 lines
2.3 KiB
Django/Jinja
# GENERE par Set-OPS (role serveur_ops). Ne pas editer a la main.
|
|
#
|
|
# LE VESTIBULE DE LA CONSOLE. Le GUI, lui, n'ecoute que la boucle locale.
|
|
#
|
|
# TOUT CE QUI EST PUBLIE PASSE PAR ICI, et l'authentification est posee au niveau du
|
|
# `server` — pas d'un `location`. Placee dans le seul bloc de relais, elle laisserait
|
|
# passer tout chemin qu'un `location` plus specifique attraperait en premier. Une
|
|
# serrure qu'on contourne par la porte d'a cote n'est pas une serrure.
|
|
server {
|
|
listen {{ serveur_ops_gui_port_public }};
|
|
listen [::]:{{ serveur_ops_gui_port_public }};
|
|
server_name {{ serveur_ops_hostname }};
|
|
{% if serveur_ops_gui_auth == 'locale' %}
|
|
|
|
# SANS ANNUAIRE : un mot de passe, et il vaut pour toute la fabric. C'est un repli
|
|
# assume, pas un choix — voir `serveur_ops_gui_auth` dans les defauts du role.
|
|
auth_basic "{{ serveur_ops_gui_realm }}";
|
|
auth_basic_user_file {{ serveur_ops_gui_htpasswd }};
|
|
{% else %}
|
|
|
|
# AVEC ANNUAIRE : c'est `serveur_oauth2_proxy` qui se tient devant, et lui seul doit
|
|
# pouvoir frapper ce port. Le pare-feu de l'hote le dit deja (`meta/flux.yml`), et on
|
|
# ne le redit pas ici : deux couches qui declarent la meme politique finissent par
|
|
# en declarer deux differentes.
|
|
{% endif %}
|
|
|
|
# LA CONSOLE DEPLOIE, ET UN DEPLOIEMENT EST LONG. Les delais par defaut de nginx
|
|
# (60 s) couperaient la reponse au milieu d'un `deployer`, et la page afficherait une
|
|
# erreur reseau pour une operation qui, elle, continue sur la machine. La pire forme
|
|
# de mensonge : l'ecran dit echec, la fabric dit succes.
|
|
proxy_read_timeout {{ serveur_ops_gui_delai | default(3600) }}s;
|
|
proxy_send_timeout {{ serveur_ops_gui_delai | default(3600) }}s;
|
|
|
|
# LA SORTIE D'UN DEPLOIEMENT ARRIVE AU FIL DE L'EAU. Sans ces deux lignes, nginx la
|
|
# retiendrait pour l'envoyer d'un bloc : la console resterait muette pendant des
|
|
# minutes, puis tout apparaitrait d'un coup.
|
|
proxy_buffering off;
|
|
gzip off;
|
|
|
|
location / {
|
|
proxy_pass http://{{ serveur_ops_gui_ecoute }}:{{ serveur_ops_gui_port }};
|
|
proxy_http_version 1.1;
|
|
proxy_set_header Host $host;
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
proxy_set_header X-Forwarded-Proto $scheme;
|
|
}
|
|
}
|