tunnel d'administration : le SSH du site et la console de la frontiere manquaient
Eprouve en production : les locataires repondaient, le site non — son SSH vient de `flotte` et vivait du rebond par la frontiere. Et rien ne designait la frontiere elle-meme, si bien que monter le tunnel faisait perdre le moyen de le corriger. Une regle par port : OPNsense refuse deux ports dans un champ. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
d90513ca91
commit
2a276fb6b4
4 changed files with 83 additions and 2 deletions
19
CHANGELOG.md
19
CHANGELOG.md
|
|
@ -1,5 +1,24 @@
|
|||
# CHANGELOG — Set-OPS
|
||||
|
||||
## 2026-09-17 (4) — Le tunnel d'administration, eprouve en production : deux trous refermes
|
||||
|
||||
Le tunnel montait, la poignee de main se faisait, une machine de LOCATAIRE repondait — et
|
||||
aucune machine du SITE, ni la console de la frontiere.
|
||||
|
||||
- **SSH des machines du site** : le socle declare son 22 en `pair: [flotte, externe]`, jamais
|
||||
`admin`. L'acces vivait du REBOND par la frontiere (la connexion part alors du boitier, que
|
||||
pf laisse sortir sans regle) ; par le tunnel, la source est exterieure et rien ne
|
||||
l'autorisait. Les locataires marchaient deja : leur regle SSH nait de `nftables_admin_ssh`.
|
||||
- **Console et API de la frontiere** : aucun flux ne la designait comme destination
|
||||
d'administration. Monter le tunnel faisait perdre le moyen de reparer la regle manquante —
|
||||
il a fallu remettre l'adresse d'avant pour appliquer le correctif.
|
||||
- **Une regle par port** : OPNsense refuse « 22,443 » (« Please specify a valid portnumber,
|
||||
name, alias or range »). Aucun flux jusqu'ici n'en portait deux.
|
||||
|
||||
Mesure, tunnel monte et adresse d'avant retiree : site-mon-01, site-ops-01, site-dnspub-01,
|
||||
les deux `infra-dns-01` des locataires et la console OPNsense (HTTP 200) repondent tous, vus
|
||||
depuis `10.37.29.2`. `make prouver` : CONFORME, 82 OK.
|
||||
|
||||
## 2026-09-17 (3) — L'administration entre par un tunnel nominatif, pas par le runner
|
||||
|
||||
Question posee : « le runner ne devrait-il pas etre le rebond SSH des admins ? » Non — il
|
||||
|
|
|
|||
|
|
@ -58,6 +58,22 @@ l'appareil. Perdue, on en tire une autre ; l'ancienne se révoque par `etat: abs
|
|||
aussi tout pair **attaché à notre instance que le plan ne déclare plus** : un accès qui
|
||||
survivrait à la décision de le retirer est exactement ce qu'on ne veut pas.
|
||||
|
||||
## Deux trous que seul l'usage a montrés (2026-09-17, une heure après la pose)
|
||||
|
||||
- **Le SSH des machines du site.** Le socle déclare son 22 en `pair: [flotte, externe]`, jamais
|
||||
`admin` : la source dérivée est le site lui-même. L'exploitant y arrivait **par rebond sur la
|
||||
frontière** — la connexion partait alors du boîtier, que pf laisse sortir sans règle. Par le
|
||||
tunnel, il arrive comme une source extérieure, et plus rien ne l'autorisait. Les locataires,
|
||||
eux, marchaient : leur règle SSH naît de `nftables_admin_ssh`, qui contient déjà le tunnel.
|
||||
- **La frontière elle-même.** Aucun flux ne la désignait comme destination d'administration :
|
||||
monter le tunnel faisait perdre sa console et son API — donc le moyen même de réparer la
|
||||
règle manquante. *La panne se referme sur celui qui la répare* : il a fallu remettre
|
||||
l'adresse d'avant pour poser le correctif.
|
||||
|
||||
Les deux règles sont désormais émises par `devis_opnsense` dès que `acces_admin_vpn` est
|
||||
déclaré (`ports_frontiere`, par défaut 22 et 443). Une règle **par port** : OPNsense refuse
|
||||
« 22,443 » dans un champ de port, et aucun flux jusque-là n'en portait deux.
|
||||
|
||||
## Ce que le tunnel donne, et ce qu'il ne donne pas
|
||||
|
||||
`AllowedIPs` est **dérivé** de la carte : zones du site, fabric, lien de transit et supernets
|
||||
|
|
|
|||
|
|
@ -55,14 +55,14 @@
|
|||
| P40 | Parente : l'ecosysteme sait de quoi il descend | — | ✅ OK | Parente coherente : 4 depot(s), tous retrouves, tous porteurs d'un remote. |
|
||||
| P41 | Resolution d'instance : une seule, partagee | — | ✅ OK | Resolution unique : 68 script(s) passent par `inventory_rules`, 3 exemption(s) nommee(s). |
|
||||
| P42 | L'edge porte les noms qu'il publie | — | ✅ OK | 5 edge(s) emettent un certificat portant les noms publies (instance-ci-1646753/production, OPS-Chezlepro-lab/principal, OPS-Chezlepro/principal, OPS-Technolibre |
|
||||
| P43 | Frontiere : le devis voit les machines du site | — | ✅ OK | Devis de la frontiere : 9 machine(s) du plan retrouvees, 197 regle(s) du site. |
|
||||
| P43 | Frontiere : le devis voit les machines du site | — | ✅ OK | Devis de la frontiere : 9 machine(s) du plan retrouvees, 200 regle(s) du site. |
|
||||
| P44 | Integrations : le serveur avant ses clients | — | ✅ OK | 5 integration(s) appliquent leur serveur avant leurs clients. |
|
||||
| P45 | Pare-feu Proxmox : arme sur les VNet SDN, jamais ailleurs | — | ✅ OK | Le pare-feu Proxmox ne s'arme que sur un VNet SDN (4 cas evalues, dont un qui doit rendre VRAI). |
|
||||
| P46 | Plancher /etc/hosts : un seul role en decide | — | ✅ OK | Un seul maitre du plancher — roles/hosts_statiques/tasks/main.yml : manage_etc_hosts: false ; et le gabarit maitre est pose (roles/hosts_statiques/templates/hos |
|
||||
| P47 | Zones inverses : couvrir l'occupe, et rien de plus | — | ✅ OK | Les zones inverses couvrent l'occupe et rien de plus (5 cas evalues, dont un site a quatre zones et un tenant a une). |
|
||||
| P48 | La carte d'orientation designe ce qui existe, et compte juste | — | ✅ OK | La carte designe 101 chemin(s) qui existent, et ses 7 chiffres correspondent a la mesure. |
|
||||
| P49 | Registre des flux : la matrice d'audit est a jour | — | ✅ OK | Le registre des flux reproduit exactement ce que les `meta/flux.yml` declarent (138 lignes). |
|
||||
| P50 | Silences : un refus muet est declare, place en dernier, et motive | — | ✅ OK | 2 silence(s) declare(s), tous en sequence > 1 (la plus haute des 299 regles `pass`), tous non consignes et tous motives. |
|
||||
| P50 | Silences : un refus muet est declare, place en dernier, et motive | — | ✅ OK | 2 silence(s) declare(s), tous en sequence > 1 (la plus haute des 302 regles `pass`), tous non consignes et tous motives. |
|
||||
| P51 | Collections : toutes declarees, toutes epinglees | — | ✅ OK | 3 collection(s) et 2 bibliotheque(s) Python declarees et epinglees : ansible.posix==1.6.2, community.general==10.3.0, community.postgresql==3.10.2 |
|
||||
| P52 | Materialiser n'exige pas d'entrer dans le tenant | — | ✅ OK | `creer-vm` confirme par l'agent invite (API des hyperviseurs, deja utilisee pour creer), sans exiger d'entrer dans le tenant. |
|
||||
| P53 | L'interne refuse a voix haute, la bordure se tait | — | ✅ OK | L'interne parle, la bordure se tait — 13 ruleset(s) nftables refusent a voix haute ; pare-feu est-ouest en REJECT, source unique ; frontiere muette (actions : b |
|
||||
|
|
|
|||
|
|
@ -1419,6 +1419,52 @@ def construire(tenants: list[tuple[str, str, dict]]) -> dict:
|
|||
"raison": _fl_f.get("raison", ""),
|
||||
})
|
||||
|
||||
# --- CE QUE LE TUNNEL D'ADMINISTRATION ATTEINT (2026-09-17, mesure en production) ---
|
||||
#
|
||||
# DEUX TROUS QUE SEUL L'USAGE A MONTRES, une heure apres la pose du tunnel :
|
||||
#
|
||||
# 1. LE SSH DES MACHINES DU SITE. Le socle declare son 22 en `pair: [flotte, externe]`,
|
||||
# jamais `admin` : la boucle des roles du site le range donc dans « flotte », dont la
|
||||
# source est le site lui-meme. L'exploitant y arrivait par REBOND sur la frontiere —
|
||||
# la connexion partait alors du boitier, que pf laisse sortir sans regle. Par le
|
||||
# tunnel, il arrive comme une source exterieure, et plus rien ne l'autorise. Les
|
||||
# locataires, eux, marchaient : leur regle SSH nait de `nftables_admin_ssh`, qui
|
||||
# contient deja le reseau du tunnel.
|
||||
#
|
||||
# 2. LA FRONTIERE ELLE-MEME. Aucun flux ne la designe comme destination
|
||||
# d'administration : monter le tunnel revenait a perdre sa console et son API — donc
|
||||
# le moyen meme de reparer la regle manquante. C'est la panne qui se referme sur
|
||||
# celui qui la repare.
|
||||
if _reseau_vpn:
|
||||
_ports_frontiere = [str(p) for p in (_vpn_admin.get("ports_frontiere") or [22, 443])]
|
||||
_cibles_vpn = [("SETOPS_SITE_SERVEUR_DEBIAN", ["22"],
|
||||
"SSH d'administration vers TOUTES les machines du site, par le tunnel "
|
||||
"nominatif. Le socle declare son 22 en `flotte` : sans cette regle, "
|
||||
"l'acces ne survit qu'au rebond par la frontiere.")]
|
||||
if _ports_frontiere:
|
||||
_cibles_vpn.append(("SETOPS_FRONTIERE", _ports_frontiere,
|
||||
"Console et API de la frontiere depuis le tunnel : sans elles, "
|
||||
"monter le tunnel fait perdre le moyen de le corriger."))
|
||||
# UNE REGLE PAR PORT (mesure du 2026-09-17). OPNsense refuse « 22,443 » dans le champ
|
||||
# `destination_port` : « Please specify a valid portnumber, name, alias or range ».
|
||||
# Ailleurs, chaque flux ne porte qu'un port et le cas ne s'etait jamais presente.
|
||||
for _dst_vpn, _ports_vpn, _raison_vpn in _cibles_vpn:
|
||||
if _dst_vpn not in alias:
|
||||
continue
|
||||
for _port_vpn in _ports_vpn:
|
||||
regles.append({
|
||||
"sens": "in",
|
||||
"interface": if_vpn,
|
||||
"protocole": "tcp",
|
||||
"source": "SETOPS_ADMIN_SITE_VPN",
|
||||
"destination": _dst_vpn,
|
||||
"ports": [_port_vpn],
|
||||
"chiffrement": "ssh" if _port_vpn == "22" else "tls",
|
||||
"role": "acces_admin_vpn",
|
||||
"tenant": "SITE",
|
||||
"raison": _raison_vpn,
|
||||
})
|
||||
|
||||
# --- LA PORTE DU TUNNEL D'ADMINISTRATION (2026-09-17) --------------------------
|
||||
#
|
||||
# Le tunnel ne peut pas s'etablir si son port n'est pas ouvert sur le WAN. C'est le SEUL
|
||||
|
|
|
|||
Loading…
Reference in a new issue