l edge servait du snakeoil, et deux ecritures d une meme regle
Le certificat bouchon de Debian sur les trois noms. serveur_nginx l a pour defaut, avec un commentaire d avant la PKI ; un locataire le remplace en group_vars, l inventaire du site est dynamique et n en a pas. Les autres replis rendaient un service muet — celui-la rend du TLS qui RESSEMBLE a du TLS : le cadenas s affiche et rien n est prouve. site_inventaire construisait sa propre liste d expositions, avec edge = le groupe de l application. Vrai tant que le site n avait pas d edge. client_pki retient un FQDN si son edge est un groupe de cet hote : aucun ne correspondait, et le certificat ne portait que le nom de la machine. La boucle est remplacee par un appel a expositions_des_applications. Et la cicatrice de site-forge-01 — un cert renouvele n atteint personne tant que son consommateur n est pas recharge — a ete refaite sur la machine suivante. Les 6 noms sont maintenant servis et verifies contre l AC du site. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
This commit is contained in:
parent
4f68182ac6
commit
fae3cc8838
2 changed files with 107 additions and 9 deletions
65
CHANGELOG.md
65
CHANGELOG.md
|
|
@ -1,5 +1,70 @@
|
||||||
# CHANGELOG — Set-OPS
|
# CHANGELOG — Set-OPS
|
||||||
|
|
||||||
|
## 2026-09-14 (23) — Du TLS qui ressemblait a du TLS, et une regle qu'un tenant n'a jamais eu besoin d'ecrire
|
||||||
|
|
||||||
|
Trois defauts de plus sur le chemin de l'edge, et le premier est le plus grave de la
|
||||||
|
journee.
|
||||||
|
|
||||||
|
### L'edge servait `ssl-cert-snakeoil.pem`
|
||||||
|
|
||||||
|
Le certificat bouchon de Debian, sur les trois noms. `serveur_nginx` l'a pour DEFAUT,
|
||||||
|
avec un commentaire qui date d'avant la PKI : *« a remplacer par des certificats de l'AC
|
||||||
|
interne plus tard »*. Un locataire le remplace dans `group_vars/serveur_nginx.yml` ;
|
||||||
|
l'inventaire du site est DYNAMIQUE et n'a pas de group_vars.
|
||||||
|
|
||||||
|
LES AUTRES REPLIS RENDAIENT UN SERVICE MUET OU UNE REGLE INERTE. Celui-la rend **du TLS
|
||||||
|
qui ressemble a du TLS** : le cadenas s'affiche, la connexion est chiffree, et rien n'est
|
||||||
|
prouve — le certificat n'est signe par personne et ne porte aucun des noms servis. C'est
|
||||||
|
la seule sorte de panne qui rassure.
|
||||||
|
|
||||||
|
### Deux ecritures d'une meme regle, et seule l'une a appris
|
||||||
|
|
||||||
|
`site_inventaire.py` construisait sa PROPRE liste d'expositions, avec `edge` = le groupe
|
||||||
|
de l'application. Le commentaire disait pourquoi : *« le site n'a pas d'edge, donc chaque
|
||||||
|
service se sert lui-meme »*. C'etait vrai jusqu'a hier.
|
||||||
|
|
||||||
|
`client_pki` retient un FQDN si son `edge` est un GROUPE DE CET HOTE. L'edge appartient a
|
||||||
|
`serveur_nginx` ; cette boucle rendait `serveur_grafana`, `serveur_icingaweb2`... Aucun
|
||||||
|
nom ne correspondait. La boucle est remplacee par un appel a
|
||||||
|
`expositions_des_applications` — la regle n'existe plus qu'une fois.
|
||||||
|
|
||||||
|
### La cicatrice refaite sur la machine suivante
|
||||||
|
|
||||||
|
`site-forge-01` porte ce commentaire depuis des semaines : *« Un cert renouvele sur disque
|
||||||
|
reste servi perime tant que le consommateur n'est pas recharge. La cicatrice est deja dans
|
||||||
|
le depot ; on ne la refait pas. »* Elle a ete refaite sur `site-edge-01`, qui n'avait pas
|
||||||
|
de `client_pki_reload_services`.
|
||||||
|
|
||||||
|
disque : forge, pki, dns, sauvegarde, observatoire, vigie, site-edge-01
|
||||||
|
servi : site-edge-01
|
||||||
|
|
||||||
|
### Ou en est l'edge
|
||||||
|
|
||||||
|
certificat servi les 6 noms, signe par l'AC du site
|
||||||
|
verification TLS verif_tls=0 depuis le poste, contre la racine du site
|
||||||
|
vhosts forge, observatoire, vigie — en 443
|
||||||
|
|
||||||
|
### CE QUI RESTE, ET C'EST UNE VRAIE PIECE
|
||||||
|
|
||||||
|
Les trois noms repondent en TLS **verifie**, puis rien : `http=000`. L'edge ne joint pas
|
||||||
|
ses amonts, et le devis le dit lui-meme :
|
||||||
|
|
||||||
|
note : serveur_nginx declare un port `derive` que le plan du site ne resout pas
|
||||||
|
— aucune regle emise.
|
||||||
|
|
||||||
|
`serveur_nginx` declare bien `egress port: derive, pair: expositions`. Ce flux n'a JAMAIS
|
||||||
|
eu besoin d'etre resolu a la frontiere : chez un locataire, les passerelles de zone sont
|
||||||
|
tenues par le SDN de Proxmox, et le trafic edge -> amont ne traverse pas le boitier. **Au
|
||||||
|
site, elles sont tenues par la frontiere** — et c'est le premier endroit ou un edge doit
|
||||||
|
franchir la bordure pour atteindre ce qu'il relaie.
|
||||||
|
|
||||||
|
Resoudre `expositions` en une regle PAR AMONT (son hote, son port) est la piece qui
|
||||||
|
manque. Elle se voit maintenant parce que le site est la premiere fabric ou un edge et
|
||||||
|
ses services vivent dans des zones differentes.
|
||||||
|
|
||||||
|
Et `forge` relaie en `http://10.37.33.11:443` — du clair vers un port TLS, d'ou son `400`.
|
||||||
|
L'amont d'une exposition deja servie en TLS doit etre `https://`.
|
||||||
|
|
||||||
## 2026-09-14 (22) — L'edge du site est debout, et quatre replis silencieux l'ont retarde
|
## 2026-09-14 (22) — L'edge du site est debout, et quatre replis silencieux l'ont retarde
|
||||||
|
|
||||||
`site-edge-01` est nee, deployee, et sert `forge`, `observatoire` et `vigie` en 443. Le
|
`site-edge-01` est nee, deployee, et sert `forge`, `observatoire` et `vigie` en 443. Le
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ from pathlib import Path
|
||||||
sys.path.insert(0, str(Path(__file__).resolve().parent))
|
sys.path.insert(0, str(Path(__file__).resolve().parent))
|
||||||
import yaml # noqa: E402
|
import yaml # noqa: E402
|
||||||
import underlay as U # noqa: E402
|
import underlay as U # noqa: E402
|
||||||
|
from inventory_rules import expositions_des_applications # noqa: E402
|
||||||
from inventory_rules import integrations_universelles # noqa: E402
|
from inventory_rules import integrations_universelles # noqa: E402
|
||||||
|
|
||||||
# L'inventaire des tenants passe par ce compte ; le site n'a aucune raison d'en differer.
|
# L'inventaire des tenants passe par ce compte ; le site n'a aucune raison d'en differer.
|
||||||
|
|
@ -386,15 +387,28 @@ def inventaire() -> dict:
|
||||||
# LES EXPOSITIONS : le nom du SERVICE, pas celui de la machine. Un nom de service
|
# LES EXPOSITIONS : le nom du SERVICE, pas celui de la machine. Un nom de service
|
||||||
# survit au demenagement du service ; un nom de machine, non.
|
# survit au demenagement du service ; un nom de machine, non.
|
||||||
#
|
#
|
||||||
# `edge` nomme le GROUPE qui sert ce FQDN — c'est ce qu'attend `hosts_statiques`.
|
# `edge` nomme le GROUPE qui sert ce FQDN — c'est ce qu'attend `hosts_statiques`, et
|
||||||
# Chez un tenant c'est l'edge nginx, qui termine le TLS pour tout le monde. Le site
|
# c'est de la que `client_pki` tire les SAN du certificat.
|
||||||
# n'a pas d'edge : chaque service se sert lui-meme, donc le groupe est le sien. La
|
#
|
||||||
# forme reste la meme, ce qui la remplit change.
|
# ON APPELLE LA FONCTION PARTAGEE, ON NE LA REECRIT PLUS (2026-09-14).
|
||||||
expositions: list[dict] = []
|
#
|
||||||
for nom_app, app in applications.items():
|
# Cette boucle disait : « le site n'a pas d'edge, donc chaque service se sert
|
||||||
for fqdn in (app.get("expose") or []):
|
# lui-meme, donc le groupe est le sien ». C'etait vrai — jusqu'au jour ou le site a
|
||||||
expositions.append({"fqdn": str(fqdn), "edge": str(app.get("groupe") or ""),
|
# eu un edge. La meme regle vivait alors a DEUX endroits : ici, et dans
|
||||||
"application": nom_app})
|
# `expositions_des_applications`, qui lit le registre des domaines. Seule la seconde
|
||||||
|
# a appris ; celle-ci est restee sur l'ancienne verite.
|
||||||
|
#
|
||||||
|
# CE QUE CA A COUTE. `client_pki` retient un FQDN si son `edge` est un GROUPE DE
|
||||||
|
# CET HOTE. L'edge appartient a `serveur_nginx` ; cette boucle rendait
|
||||||
|
# `serveur_grafana`, `serveur_icingaweb2`... Aucun nom ne correspondait, et le
|
||||||
|
# certificat de `site-edge-01` ne portait QUE celui de la machine — du TLS correct
|
||||||
|
# sur trois noms que personne ne peut appeler.
|
||||||
|
#
|
||||||
|
# Deux ecritures d'une meme regle finissent par diverger. Celle-ci n'existe plus.
|
||||||
|
expositions = expositions_des_applications(
|
||||||
|
{"applications": applications},
|
||||||
|
{"domaines_publics": (U.lire_plan_site("domaines.yml") or {}).get("domaines_publics") or {}},
|
||||||
|
)
|
||||||
|
|
||||||
# --- LES GARDES DU PLAN, LA OU LE PLAN EST LU ----------------------------
|
# --- LES GARDES DU PLAN, LA OU LE PLAN EST LU ----------------------------
|
||||||
#
|
#
|
||||||
|
|
@ -666,6 +680,25 @@ def inventaire() -> dict:
|
||||||
# un. Les deux autres modes d'Icinga Web 2 (`ldap`, `external`) supposent
|
# un. Les deux autres modes d'Icinga Web 2 (`ldap`, `external`) supposent
|
||||||
# l'un ou l'autre ; ici, nginx authentifie et l'application le croit.
|
# l'un ou l'autre ; ici, nginx authentifie et l'application le croit.
|
||||||
"serveur_icingaweb2_auth": "locale",
|
"serveur_icingaweb2_auth": "locale",
|
||||||
|
# L'EDGE SERT LE CERTIFICAT DE L'AC INTERNE, PAS LE BOUCHON DE DEBIAN.
|
||||||
|
#
|
||||||
|
# `serveur_nginx` a pour DEFAUT `ssl-cert-snakeoil.pem`, avec un commentaire
|
||||||
|
# qui date d'avant la PKI : « a remplacer par des certificats de l'AC interne
|
||||||
|
# plus tard ». Chez un locataire, `group_vars/serveur_nginx.yml` le remplace.
|
||||||
|
# L'inventaire du site est DYNAMIQUE et n'a pas de group_vars : l'edge est
|
||||||
|
# donc ne en servant du snakeoil.
|
||||||
|
#
|
||||||
|
# C'EST LE PLUS GRAVE DES REPLIS DE LA JOURNEE. Les autres rendaient un
|
||||||
|
# service muet ou une regle inerte — celui-la rend du TLS qui RESSEMBLE a du
|
||||||
|
# TLS. Le cadenas s'affiche, la connexion est chiffree, et rien n'est prouve :
|
||||||
|
# le certificat servi n'est signe par personne et ne porte aucun des noms.
|
||||||
|
#
|
||||||
|
# Le chemin est celui que `client_pki` ecrit, et le meme que celui des
|
||||||
|
# locataires — une seule convention, pas deux.
|
||||||
|
"serveur_nginx_certificat":
|
||||||
|
"/etc/step/certs/{{ ansible_fqdn | default(ansible_hostname) }}.crt",
|
||||||
|
"serveur_nginx_cle":
|
||||||
|
"/etc/step/certs/{{ ansible_fqdn | default(ansible_hostname) }}.key",
|
||||||
# Le depot du site, pour les machines du site qui y deposent. Vide s'il n'y
|
# Le depot du site, pour les machines du site qui y deposent. Vide s'il n'y
|
||||||
# en a pas — `client_backup` refuse alors, plutot que de viser un nom qui
|
# en a pas — `client_backup` refuse alors, plutot que de viser un nom qui
|
||||||
# ne repond pas : mieux vaut un deploiement qui s'arrete qu'une sauvegarde
|
# ne repond pas : mieux vaut un deploiement qui s'arrete qu'une sauvegarde
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue