frontière : le prochain saut dérive du transit, il n'est plus saisi
`opnsense_prochain_saut` quitte le panneau Intrants. Il dérive du réseau de transit de l'underlay — la `passerelle` du réseau portant `passerelle_sortie`. Un seul bloc alimente les deux devis : 10.0.4.1 est le SVI côté switch ET le prochain saut des routes tenants côté frontière ; 10.0.4.2 est la route par défaut du switch. Le saisir en doublon rouvrait la possibilité de deux valeurs contradictoires pour un seul lien — le mode de panne qu'on venait de fermer pour les réseaux d'administration. Le devis frontière expose le bloc `transit` (JSON compris) et cesse de réclamer en section 0 les routes que `devis-reseau` émet désormais : il dit lesquelles sont déjà émises, ou signale l'absence de transit déclaré. Sans underlay, le marqueur revient — le repli reste explicite. Preuves : 24 OK, 0 échec. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
3698152b6a
commit
069e549160
4 changed files with 75 additions and 6 deletions
19
CHANGELOG.md
19
CHANGELOG.md
|
|
@ -1,5 +1,24 @@
|
||||||
# CHANGELOG — Set-OPS
|
# CHANGELOG — Set-OPS
|
||||||
|
|
||||||
|
## 2026-08-01 (suite) — le prochain saut dérive du transit
|
||||||
|
|
||||||
|
`opnsense_prochain_saut` n'est plus un intrant du panneau : il **dérive** du réseau de
|
||||||
|
transit de l'underlay (la `passerelle` du réseau portant `passerelle_sortie`).
|
||||||
|
|
||||||
|
Un seul bloc de six lignes alimente désormais les deux devis : `10.0.4.1` devient le SVI
|
||||||
|
côté switch **et** le prochain saut des routes tenants côté frontière ; `10.0.4.2` devient
|
||||||
|
la route par défaut du switch. Le saisir en doublon dans le panneau rouvrait la possibilité
|
||||||
|
de deux valeurs contradictoires pour un seul lien — précisément le mode de panne qu'on venait
|
||||||
|
de fermer pour les réseaux d'administration.
|
||||||
|
|
||||||
|
Le devis frontière gagne au passage un bloc `transit` (JSON compris) et cesse de réclamer en
|
||||||
|
section 0 des routes que `make devis-reseau` émet maintenant : il dit lesquelles sont **déjà
|
||||||
|
émises**, ou signale l'absence de transit déclaré. Sans underlay, le marqueur
|
||||||
|
`<PROCHAIN-SAUT-SWITCH>` revient — le repli reste explicite.
|
||||||
|
|
||||||
|
Reste un seul intrant à figer au câblage : `opnsense_if_transit`, le nom de l'interface qui
|
||||||
|
porte le VLAN 40 sur le boîtier — la seule valeur que rien ne peut deviner.
|
||||||
|
|
||||||
## 2026-08-01 — le lien de transit et les deux routes (la boucle est fermée)
|
## 2026-08-01 — le lien de transit et les deux routes (la boucle est fermée)
|
||||||
|
|
||||||
### Ajouté — réseau de transit dans l'underlay (clé `passerelle_sortie`)
|
### Ajouté — réseau de transit dans l'underlay (clé `passerelle_sortie`)
|
||||||
|
|
|
||||||
|
|
@ -77,6 +77,12 @@ Un `/29` plutôt qu'un `/30` : pendant une transition, deux pare-feux cohabitent
|
||||||
et un `/30` n'offre que deux adresses. `make underlay` (**preuve P23**) refuse une sortie hors
|
et un `/30` n'offre que deux adresses. `make underlay` (**preuve P23**) refuse une sortie hors
|
||||||
du lien, confondue avec le SVI, sans SVI, ou déclarée deux fois.
|
du lien, confondue avec le SVI, sans SVI, ou déclarée deux fois.
|
||||||
|
|
||||||
|
Ce seul bloc alimente **les deux devis** : le `passerelle` (`10.0.4.1`) devient le SVI côté
|
||||||
|
switch *et* le prochain saut des routes tenants côté frontière ; le `passerelle_sortie`
|
||||||
|
(`10.0.4.2`) devient la route par défaut du switch. Le prochain saut n'est donc **pas** un
|
||||||
|
intrant du panneau — le saisir en doublon rouvrirait la possibilité de deux valeurs
|
||||||
|
contradictoires pour un seul et même lien.
|
||||||
|
|
||||||
### Les deux routes, et pourquoi il en faut deux
|
### Les deux routes, et pourquoi il en faut deux
|
||||||
|
|
||||||
`make devis-reseau` émet alors, en section 5 :
|
`make devis-reseau` émet alors, en section 5 :
|
||||||
|
|
@ -155,9 +161,10 @@ ansible-vault edit instance/inventories/principal/group_vars/all/vault.yml
|
||||||
## 6. Ce qui reste ouvert
|
## 6. Ce qui reste ouvert
|
||||||
|
|
||||||
- **Le câblage** — le lien de transit est *décidé* (VLAN 40, `10.0.4.0/29`) et le devis
|
- **Le câblage** — le lien de transit est *décidé* (VLAN 40, `10.0.4.0/29`) et le devis
|
||||||
switch émet déjà son SVI et ses routes. Restent à figer, une fois le boîtier raccordé, les
|
switch émet déjà son SVI et ses routes. Reste à figer, une fois le boîtier raccordé, un
|
||||||
deux intrants côté frontière : `opnsense_if_transit` (l'interface qui porte le VLAN 40) et
|
seul intrant : `opnsense_if_transit`, le nom de l'interface qui porte le VLAN 40 sur le
|
||||||
`opnsense_prochain_saut` (`10.0.4.1`).
|
boîtier — la seule valeur que rien ne peut deviner. Le prochain saut, lui, **dérive** du
|
||||||
|
transit (voir §4).
|
||||||
- **Le second VPN** — pendant la transition, le VPN d'administration actuel (pfSense) reste
|
- **Le second VPN** — pendant la transition, le VPN d'administration actuel (pfSense) reste
|
||||||
en service et OPNsense en montera un second. Son sous-réseau devra être **ajouté à
|
en service et OPNsense en montera un second. Son sous-réseau devra être **ajouté à
|
||||||
`nftables_admin_ssh`**, sans quoi il sera muet de la même façon.
|
`nftables_admin_ssh`**, sans quoi il sera muet de la même façon.
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,9 @@ from resoudre_flux import ( # noqa: E402
|
||||||
_sources_admin_ssh,
|
_sources_admin_ssh,
|
||||||
)
|
)
|
||||||
from devis_reseau import decouvrir, prefixe # noqa: E402
|
from devis_reseau import decouvrir, prefixe # noqa: E402
|
||||||
|
# Le lien de transit (et donc le prochain saut) vit dans l'underlay : il est PARTAGE
|
||||||
|
# par tous les tenants, il ne peut deriver d'aucun index. Source unique, pas un intrant.
|
||||||
|
import underlay as underlay_mod # noqa: E402
|
||||||
|
|
||||||
# Marqueurs de repli, tant que les intrants de frontiere ne sont pas renseignes
|
# Marqueurs de repli, tant que les intrants de frontiere ne sont pas renseignes
|
||||||
# (meme idiome que devis_reseau). Le panneau « Intrants de base » du GUI les ecrit
|
# (meme idiome que devis_reseau). Le panneau « Intrants de base » du GUI les ecrit
|
||||||
|
|
@ -70,6 +73,22 @@ def _ou_marqueur(intrants: dict, cle: str, marqueur: str) -> str:
|
||||||
valeur = str(intrants.get(cle) or "").strip()
|
valeur = str(intrants.get(cle) or "").strip()
|
||||||
return valeur or marqueur
|
return valeur or marqueur
|
||||||
|
|
||||||
|
|
||||||
|
def transit_underlay() -> dict | None:
|
||||||
|
"""Le reseau de transit declare dans l'underlay, ou None."""
|
||||||
|
return underlay_mod.reseau_transit(underlay_mod.charger())
|
||||||
|
|
||||||
|
|
||||||
|
def prochain_saut(transit: dict | None) -> str:
|
||||||
|
"""Prochain saut des routes tenants = le SVI du switch sur le lien de transit.
|
||||||
|
|
||||||
|
DERIVE, jamais saisi : c'est le meme lien que celui d'ou `devis_reseau` tire la
|
||||||
|
route par defaut et les routes de retour. Le declarer deux fois (une fois ici, une
|
||||||
|
fois dans l'underlay) ouvrirait la porte a deux valeurs contradictoires — c'est
|
||||||
|
exactement le mode de panne qu'on ferme. Marqueur tant qu'aucun transit n'existe.
|
||||||
|
"""
|
||||||
|
return str((transit or {}).get("passerelle") or "").strip() or PROCHAIN_SAUT
|
||||||
|
|
||||||
# Le socle est porte par TOUS les hotes : sa destination n'est pas une poignee
|
# Le socle est porte par TOUS les hotes : sa destination n'est pas une poignee
|
||||||
# de machines mais le supernet du tenant. Evite un alias de 14 adresses.
|
# de machines mais le supernet du tenant. Evite un alias de 14 adresses.
|
||||||
ROLE_SOCLE = "serveur_debian"
|
ROLE_SOCLE = "serveur_debian"
|
||||||
|
|
@ -177,7 +196,8 @@ def construire(tenants: list[tuple[str, str, dict]]) -> dict:
|
||||||
})
|
})
|
||||||
|
|
||||||
intrants = intrants_frontiere()
|
intrants = intrants_frontiere()
|
||||||
saut = _ou_marqueur(intrants, "opnsense_prochain_saut", PROCHAIN_SAUT)
|
transit = transit_underlay()
|
||||||
|
saut = prochain_saut(transit)
|
||||||
routes = [
|
routes = [
|
||||||
{
|
{
|
||||||
"reseau": supernet_de(n["index"]),
|
"reseau": supernet_de(n["index"]),
|
||||||
|
|
@ -198,6 +218,13 @@ def construire(tenants: list[tuple[str, str, dict]]) -> dict:
|
||||||
"routes": routes,
|
"routes": routes,
|
||||||
"regles": regles,
|
"regles": regles,
|
||||||
"admin": admin,
|
"admin": admin,
|
||||||
|
"transit": {
|
||||||
|
"nom": (transit or {}).get("nom"),
|
||||||
|
"vlan": (transit or {}).get("vlan"),
|
||||||
|
"sous_reseau": (transit or {}).get("sous_reseau"),
|
||||||
|
"svi_switch": saut,
|
||||||
|
"adresse_frontiere": (transit or {}).get("passerelle_sortie"),
|
||||||
|
} if transit else None,
|
||||||
"reciproque_switch": [
|
"reciproque_switch": [
|
||||||
f"ip route {cidr} -> {saut} (retour vers l'administration)"
|
f"ip route {cidr} -> {saut} (retour vers l'administration)"
|
||||||
for cidr in admin
|
for cidr in admin
|
||||||
|
|
@ -214,17 +241,31 @@ def rendre(devis: dict) -> str:
|
||||||
"# Les passerelles de zone restent sur les switches L3 : aucun SVI ici.",
|
"# Les passerelles de zone restent sur les switches L3 : aucun SVI ici.",
|
||||||
"# ============================================================",
|
"# ============================================================",
|
||||||
"",
|
"",
|
||||||
"## 0. Prerequis reciproques — A FAIRE SUR LES SWITCHES",
|
"## 0. Prerequis reciproques — COTE SWITCHES",
|
||||||
"# Sans ces routes de retour, le trafic part mais ne revient pas : la",
|
"# Sans ces routes de retour, le trafic part mais ne revient pas : la",
|
||||||
"# reponse sort par une autre interface et le pare-feu la jette (hors etat).",
|
"# reponse sort par une autre interface et le pare-feu la jette (hors etat).",
|
||||||
]
|
]
|
||||||
out += [f"# {r}" for r in devis["reciproque_switch"]] or ["# (aucun reseau d'administration declare)"]
|
out += [f"# {r}" for r in devis["reciproque_switch"]] or ["# (aucun reseau d'administration declare)"]
|
||||||
|
tr = devis.get("transit")
|
||||||
|
if tr:
|
||||||
|
out.append(f"# DEJA EMIS par `make devis-reseau` (section 5), derive du transit"
|
||||||
|
f" '{tr['nom']}' de l'underlay.")
|
||||||
|
else:
|
||||||
|
out.append("# A EMETTRE : aucun reseau de transit n'est declare dans underlay.yml")
|
||||||
|
out.append("# (cle `passerelle_sortie`). Sans lui, ni sortie ni retour ne sont derivables.")
|
||||||
out += [
|
out += [
|
||||||
"",
|
"",
|
||||||
"## 1. Interfaces",
|
"## 1. Interfaces",
|
||||||
f"# Gestion : {devis['api_url'] or '(intrant opnsense_api_url a renseigner)'}",
|
f"# Gestion : {devis['api_url'] or '(intrant opnsense_api_url a renseigner)'}",
|
||||||
f"# WAN : {devis['if_wan']}",
|
f"# WAN : {devis['if_wan']}",
|
||||||
f"# TRANSIT : {devis['if_transit']} (trunk 802.1Q vers les switches)",
|
f"# TRANSIT : {devis['if_transit']} (trunk 802.1Q vers les switches)",
|
||||||
|
]
|
||||||
|
if tr:
|
||||||
|
out += [
|
||||||
|
f"# lien '{tr['nom']}' {tr['sous_reseau']} — VLAN {tr['vlan']} a etiqueter",
|
||||||
|
f"# switch {tr['svi_switch']} <-> frontiere {tr['adresse_frontiere']}",
|
||||||
|
]
|
||||||
|
out += [
|
||||||
"",
|
"",
|
||||||
"## 2. Routes statiques (vers les supernets tenants)",
|
"## 2. Routes statiques (vers les supernets tenants)",
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -115,7 +115,9 @@ INTRANTS_SCHEMA = [
|
||||||
("opnsense_api_verifier_certs", "frontiere", "defaut", "Frontière", "Valider le certificat TLS de la frontière", "bool"),
|
("opnsense_api_verifier_certs", "frontiere", "defaut", "Frontière", "Valider le certificat TLS de la frontière", "bool"),
|
||||||
("opnsense_if_wan", "frontiere", "defaut", "Frontière", "Interface WAN", "str"),
|
("opnsense_if_wan", "frontiere", "defaut", "Frontière", "Interface WAN", "str"),
|
||||||
("opnsense_if_transit", "frontiere", "defaut", "Frontière", "Interface/trunk vers les switches (transit)", "str"),
|
("opnsense_if_transit", "frontiere", "defaut", "Frontière", "Interface/trunk vers les switches (transit)", "str"),
|
||||||
("opnsense_prochain_saut", "frontiere", "defaut", "Frontière", "IP du switch L3 qui porte les SVI (prochain saut des routes tenants)", "str"),
|
# `opnsense_prochain_saut` n'est PLUS un intrant : il derive du reseau de transit de
|
||||||
|
# l'underlay (`passerelle` du reseau portant `passerelle_sortie`). Le saisir ici en
|
||||||
|
# doublon ouvrirait la porte a deux valeurs contradictoires pour un seul lien.
|
||||||
]
|
]
|
||||||
# Cles secretes : interdites a l'ecriture par le GUI (garde-fou).
|
# Cles secretes : interdites a l'ecriture par le GUI (garde-fou).
|
||||||
INTRANTS_CLES_INTERDITES = {
|
INTRANTS_CLES_INTERDITES = {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue