artefacts : le chainage des caches, et la regle qui appartient au SITE
Une regle inter-tenant n'appartient ni a l'emetteur ni au recepteur : c'est le site qui autorise un flux entre deux de ses tenants, et son runner qui prepare le terrain. Deux silences fermes dans le generateur de frontiere. flux_frontiere() ne retenait que les flux `externe` -- or deux tenants vivent sur des VLAN routes par la frontiere, leur trafic la traverse. Et un egress vers un voisin recevait !SETOPS_INTERNES en destination : le port ouvert vers l'INTERNET. La destination est desormais nommee. Deux roles parce que meta/flux.yml est statique : un role unique aurait declare l'ingress pour TOUS les caches -- maillage complet, visible au devis. serveur_artefacts_site porte l'ingress, serveur_artefacts l'egress vers l'amont. Debian est desormais telecharge une fois pour toute la fabric. Le cache du site ne voit que des requetes agregees, jamais quelle machine installe quoi. Rien n'est applique : le devis se lit avant. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
c391d1ed30
commit
fa7e656844
11 changed files with 236 additions and 9 deletions
63
CHANGELOG.md
63
CHANGELOG.md
|
|
@ -1,5 +1,68 @@
|
||||||
# CHANGELOG — Set-OPS
|
# CHANGELOG — Set-OPS
|
||||||
|
|
||||||
|
## 2026-08-24 — Le chaînage des caches, et la règle qui appartient au SITE
|
||||||
|
|
||||||
|
Le runner de SITE est le seul à toucher la configuration système du matériel. Sa
|
||||||
|
responsabilité est de **préparer le terrain** — VNets, routes, flux — pour que le plan
|
||||||
|
d'un OPS puisse tenir. Ensuite le runner du tenant fait la suite.
|
||||||
|
|
||||||
|
Cette mise au point tranche une question restée ouverte : **une règle inter-tenant
|
||||||
|
n'appartient ni à l'émetteur ni au récepteur, mais au site**. Ce n'est pas « Chezlepro
|
||||||
|
ouvre une porte chez patient 0 » — c'est le site qui autorise un flux entre deux de ses
|
||||||
|
tenants.
|
||||||
|
|
||||||
|
### Ce que je croyais, et qui était faux
|
||||||
|
|
||||||
|
J'avais annoncé que le générateur construisait « tenant par tenant, sur les interfaces de
|
||||||
|
ce tenant », et que des règles croisées changeraient sa forme. **Faux** : il fait une seule
|
||||||
|
passe sur tous les tenants du site, et il n'y a qu'**une interface de transit**. Les
|
||||||
|
tenants s'y distinguent par leur **alias source**, pas par leur interface.
|
||||||
|
|
||||||
|
### Deux silences fermés dans le générateur
|
||||||
|
|
||||||
|
`flux_frontiere()` ne retenait que les flux `externe`. Or deux tenants d'une même fabric
|
||||||
|
vivent sur des VLAN distincts, **routés par la frontière** : leur trafic la traverse, donc
|
||||||
|
elle doit le porter. Sans ça, le mot `voisins_site` était accepté par la validation et
|
||||||
|
rendait **zéro règle** — un flux déclaré que personne n'applique.
|
||||||
|
|
||||||
|
Et un `egress` vers un voisin recevait `!SETOPS_INTERNES` en destination, comme tout flux
|
||||||
|
sortant — c'est-à-dire **le port ouvert vers l'Internet**. La destination est désormais
|
||||||
|
**nommée**.
|
||||||
|
|
||||||
|
### Deux rôles, parce que les flux sont statiques
|
||||||
|
|
||||||
|
Un rôle unique aurait dû déclarer l'ingress inter-tenant pour **tous** les caches. Le devis
|
||||||
|
l'a montré avant toute application :
|
||||||
|
|
||||||
|
```
|
||||||
|
+ TENANT_PATI29 -> CHEZ17_SERVEUR_ARTEFACTS un maillage complet,
|
||||||
|
+ TENANT_TECH23 -> CHEZ17_SERVEUR_ARTEFACTS chaque cache acceptant chaque autre
|
||||||
|
```
|
||||||
|
|
||||||
|
`serveur_artefacts_site` porte donc l'ingress, `serveur_artefacts` l'egress vers son amont.
|
||||||
|
Résultat au devis : **l'ingress ne vise plus que le cache du site**.
|
||||||
|
|
||||||
|
### Ce que ça donne
|
||||||
|
|
||||||
|
```
|
||||||
|
VM du tenant -> cache du tenant -> cache du SITE -> Debian
|
||||||
|
```
|
||||||
|
|
||||||
|
Debian téléchargé **une fois pour toute la fabric**. Un seul flux nouveau par écosystème,
|
||||||
|
entre deux caches — jamais d'une VM vers le cache d'un voisin. Et le cache du site ne voit
|
||||||
|
que des requêtes **agrégées** : jamais quelle machine installe quoi.
|
||||||
|
|
||||||
|
Vider `serveur_artefacts_amont`, c'est s'émanciper.
|
||||||
|
|
||||||
|
### Ce qui reste large, et que je ne cache pas
|
||||||
|
|
||||||
|
L'`egress` autorise chaque cache de tenant à joindre le 3142 de **tous** ses voisins, alors
|
||||||
|
qu'un seul lui sert d'amont. La déclaration étant statique, le rôle ne sait pas lequel de
|
||||||
|
ses voisins est le cache du site. La portée effective reste juste — seul le cache du site
|
||||||
|
accepte — mais la règle sortante est plus permissive que nécessaire.
|
||||||
|
|
||||||
|
**Rien n'a été appliqué.** Le devis se lit avant.
|
||||||
|
|
||||||
## 2026-08-24 — `voisins_site` : le vocabulaire d'un flux entre tenants, et le mur qu'il révèle
|
## 2026-08-24 — `voisins_site` : le vocabulaire d'un flux entre tenants, et le mur qu'il révèle
|
||||||
|
|
||||||
Le registre des flux connaissait `flotte` (mon écosystème), `edge`, `admin` et `externe`.
|
Le registre des flux connaissait `flotte` (mon écosystème), `edge`, `admin` et `externe`.
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@
|
||||||
| P06 | Validateurs de registres (serveurs/apps/bases/domaines) | AFF-003 | ✅ OK | Registre des domaines valide. |
|
| P06 | Validateurs de registres (serveurs/apps/bases/domaines) | AFF-003 | ✅ OK | Registre des domaines valide. |
|
||||||
| P07 | GUI (node --check) | AFF-033 | ✅ OK | JS du GUI : syntaxe valide (node --check). |
|
| P07 | GUI (node --check) | AFF-033 | ✅ OK | JS du GUI : syntaxe valide (node --check). |
|
||||||
| P08 | Orchestration (couches + graphe) | AFF-070 | ✅ OK | Orchestration coherente : 35 groupes classes, aucun cycle, aucune arete en arriere. |
|
| P08 | Orchestration (couches + graphe) | AFF-070 | ✅ OK | Orchestration coherente : 35 groupes classes, aucun cycle, aucune arete en arriere. |
|
||||||
| P09 | Flux reseau (schema + matrice) | AFF-071 | ✅ OK | Flux coherents : 33 rôles, 84 flux, schéma + matrice OK. |
|
| P09 | Flux reseau (schema + matrice) | AFF-071 | ✅ OK | Flux coherents : 34 rôles, 86 flux, schéma + matrice OK. |
|
||||||
| P10 | Handlers <-> notify | AFF-034, AFF-035 | ✅ OK | Tout notify pointe vers un handler du meme role (49 roles). |
|
| P10 | Handlers <-> notify | AFF-034, AFF-035 | ✅ OK | Tout notify pointe vers un handler du meme role (49 roles). |
|
||||||
| P11 | Syntaxe des playbooks (--syntax-check) | AFF-083 | ✅ OK | playbook: playbooks/proxmox/cloner_vm_debian.yml |
|
| P11 | Syntaxe des playbooks (--syntax-check) | AFF-083 | ✅ OK | playbook: playbooks/proxmox/cloner_vm_debian.yml |
|
||||||
| P12 | Existence des runbooks cites | AFF-010, AFF-011, AFF-012, AFF-083 | ✅ OK | 17/17 runbooks/registres cites presents. |
|
| P12 | Existence des runbooks cites | AFF-010, AFF-011, AFF-012, AFF-083 | ✅ OK | 17/17 runbooks/registres cites presents. |
|
||||||
|
|
@ -36,21 +36,21 @@
|
||||||
| P21 | Federation : aucun index en collision | AFF-102 | ✅ OK | Federation coherente : 3 instance(s) federee(s), aucun index en collision. |
|
| P21 | Federation : aucun index en collision | AFF-102 | ✅ OK | Federation coherente : 3 instance(s) federee(s), aucun index en collision. |
|
||||||
| P22 | Plan de recette a jour (genere du wiki) | AFF-002 | ✅ OK | Plan de recette à jour (22 sections). |
|
| P22 | Plan de recette a jour (genere du wiki) | AFF-002 | ✅ OK | Plan de recette à jour (22 sections). |
|
||||||
| P23 | Underlay sans collision avec la plage tenant | AFF-103 | ✅ OK | Underlay conforme : 7 reseau(x), aucune collision avec la plage tenant. |
|
| P23 | Underlay sans collision avec la plage tenant | AFF-103 | ✅ OK | Underlay conforme : 7 reseau(x), aucune collision avec la plage tenant. |
|
||||||
| P24 | Frontiere nord/sud : acces d'administration declare | AFF-104 | ✅ OK | CONFORME : frontiere nord/sud, 54 regles, 15 routes, admin=10.0.0.0/24,10.17.0.0/24,10.29.19.41/32,192.168.254.2/32,192.168.255.2/32. |
|
| P24 | Frontiere nord/sud : acces d'administration declare | AFF-104 | ✅ OK | CONFORME : frontiere nord/sud, 62 regles, 15 routes, admin=10.0.0.0/24,10.17.0.0/24,10.29.19.41/32,192.168.254.2/32,192.168.255.2/32. |
|
||||||
| P25 | Pare-feu Proxmox : est-ouest intra-tenant derive | AFF-107 | ✅ OK | CONFORME : pare-feu Proxmox, 3 tenant(s), 53 groupe(s), 85 regle(s). |
|
| P25 | Pare-feu Proxmox : est-ouest intra-tenant derive | AFF-107 | ✅ OK | CONFORME : pare-feu Proxmox, 3 tenant(s), 54 groupe(s), 86 regle(s). |
|
||||||
| P26 | Integrations universelles : aucun hote laisse de cote | AFF-108 | ✅ OK | 15 hote(s) x 5 integration(s) universelle(s) : aucune lacune, aucune recopie (0 exemption(s) derivee(s) du service rendu). |
|
| P26 | Integrations universelles : aucun hote laisse de cote | AFF-108 | ✅ OK | 15 hote(s) x 5 integration(s) universelle(s) : aucune lacune, aucune recopie (0 exemption(s) derivee(s) du service rendu). |
|
||||||
| P27 | Propriete des intrants : hebergeur et tenant separes | AFF-109 | ✅ OK | 8 cle(s) de cluster chez l'hebergeur, aucune recopiee dans les group_vars du tenant. |
|
| P27 | Propriete des intrants : hebergeur et tenant separes | AFF-109 | ✅ OK | 8 cle(s) de cluster chez l'hebergeur, aucune recopiee dans les group_vars du tenant. |
|
||||||
| P28 | Pools Proxmox : un par tenant, sans collision | AFF-110 | ✅ OK | CONFORME : 3 pool(s) Proxmox, 35 VM placee(s), aucun nom ni VMID en collision. |
|
| P28 | Pools Proxmox : un par tenant, sans collision | AFF-110 | ✅ OK | CONFORME : 3 pool(s) Proxmox, 35 VM placee(s), aucun nom ni VMID en collision. |
|
||||||
| P29 | Authentification : chaque role declare sa position | AFF-111 | ✅ OK | 27 role(s) serveur declares (interne-sans-auth 2, ldap-direct 2, sans-auth-humaine 16, socle-identite 2, web-sso 5) ; 2 lacune(s) nommee(s) : serveur_loki, serv |
|
| P29 | Authentification : chaque role declare sa position | AFF-111 | ✅ OK | 28 role(s) serveur declares (interne-sans-auth 2, ldap-direct 2, sans-auth-humaine 17, socle-identite 2, web-sso 5) ; 2 lacune(s) nommee(s) : serveur_loki, serv |
|
||||||
| P30 | SDN EVPN : zones, VNets et sous-reseaux derives | AFF-112 | ✅ OK | CONFORME : SDN EVPN, 3 zone(s), 15 VNet(s), 15 sous-reseau(x), aucune collision. |
|
| P30 | SDN EVPN : zones, VNets et sous-reseaux derives | AFF-112 | ✅ OK | CONFORME : SDN EVPN, 3 zone(s), 15 VNet(s), 15 sous-reseau(x), aucune collision. |
|
||||||
| P31 | Documentation : tout ce que le depot FAIT est nomme | — | ✅ OK | 47 scripts expliques et atteignables, 98 cibles make documentees, 59 roles avec README. |
|
| P31 | Documentation : tout ce que le depot FAIT est nomme | — | ✅ OK | 47 scripts expliques et atteignables, 98 cibles make documentees, 60 roles avec README. |
|
||||||
| P32 | Intrants exiges par les roles : tous fournis | — | ✅ OK | CONFORME : 37 exigence(s) de role, toutes satisfaites (121 cle(s) declaree(s) par l'instance). |
|
| P32 | Intrants exiges par les roles : tous fournis | — | ✅ OK | CONFORME : 37 exigence(s) de role, toutes satisfaites (122 cle(s) declaree(s) par l'instance). |
|
||||||
| P33 | Aucune collision de port entre roles co-localises | — | ✅ OK | CONFORME : 32 revendication(s) de port, aucune collision entre roles co-localises (37 groupes). |
|
| P33 | Aucune collision de port entre roles co-localises | — | ✅ OK | CONFORME : 33 revendication(s) de port, aucune collision entre roles co-localises (37 groupes). |
|
||||||
| P34 | Chaque document declare son lecteur | — | ✅ OK | 42 document(s) declarent leur lecteur (22 genere(s) exempte(s)). |
|
| P34 | Chaque document declare son lecteur | — | ✅ OK | 42 document(s) declarent leur lecteur (22 genere(s) exempte(s)). |
|
||||||
| P35 | Toute application exigeant une base en a une au plan | — | ✅ OK | 5 application(s) exigeant une base l'ont toutes (4 entree(s) au registre). |
|
| P35 | Toute application exigeant une base en a une au plan | — | ✅ OK | 5 application(s) exigeant une base l'ont toutes (4 entree(s) au registre). |
|
||||||
| P36 | Tout detenteur d'etat porte une sauvegarde | — | ✅ OK | 9 hote(s) detiennent de l'etat, tous porteurs de `client_backup` (9 groupe(s) au catalogue). |
|
| P36 | Tout detenteur d'etat porte une sauvegarde | — | ✅ OK | 9 hote(s) detiennent de l'etat, tous porteurs de `client_backup` (9 groupe(s) au catalogue). |
|
||||||
| P37 | Le placement du tenant existe chez son hebergeur | — | ✅ OK | placement confronte a l'hebergeur monte (SITE-Chezlepro) : noeud, stockage, pont — tous offerts. |
|
| P37 | Le placement du tenant existe chez son hebergeur | — | ✅ OK | placement confronte a l'hebergeur monte (SITE-Chezlepro) : noeud, stockage, pont — tous offerts. |
|
||||||
| P38 | Catalogue des services : la carte dit ce que le moteur fait | — | ✅ OK | Catalogue a jour : 34 role(s) serveur/client tous nommes, 35 groupe(s) cite(s) en table existent tous. |
|
| P38 | Catalogue des services : la carte dit ce que le moteur fait | — | ✅ OK | Catalogue a jour : 35 role(s) serveur/client tous nommes, 36 groupe(s) cite(s) en table existent tous. |
|
||||||
| P39 | Glossaire : tout mot employe est enseigne | — | ✅ OK | Glossaire complet : 81 terme(s) du jargon expliques, 15 lien(s) valides, 27 page(s) de wiki toutes atteignables. |
|
| P39 | Glossaire : tout mot employe est enseigne | — | ✅ OK | Glossaire complet : 81 terme(s) du jargon expliques, 15 lien(s) valides, 27 page(s) de wiki toutes atteignables. |
|
||||||
| P40 | Parente : l'ecosysteme sait de quoi il descend | — | ✅ OK | Parente coherente : 4 depot(s), tous retrouves, tous porteurs d'un remote. |
|
| 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 : 43 script(s) passent par `inventory_rules`, 3 exemption(s) nommee(s). |
|
| P41 | Resolution d'instance : une seule, partagee | — | ✅ OK | Resolution unique : 43 script(s) passent par `inventory_rules`, 3 exemption(s) nommee(s). |
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,7 @@ Ce que la reconstruction couvre, par capacité :
|
||||||
| Source d'artefacts | `serveur_artefacts`, `client_artefacts` | cache apt de l'ecosysteme (apt-cacher-ng) : les paquets viennent de chez soi, pas de six serveurs etrangers — **mode hors ligne** pour prouver ce que le cache detient vraiment |
|
| Source d'artefacts | `serveur_artefacts`, `client_artefacts` | cache apt de l'ecosysteme (apt-cacher-ng) : les paquets viennent de chez soi, pas de six serveurs etrangers — **mode hors ligne** pour prouver ce que le cache detient vraiment |
|
||||||
| Runner de site | `serveur_ops_site` | le pouvoir de **materialiser** : creer et detruire des VM sur la fabric. Detient la voute du SITE, chiffree, et n'entre JAMAIS chez un tenant — reserve a l'ecosysteme de l'hebergeur |
|
| Runner de site | `serveur_ops_site` | le pouvoir de **materialiser** : creer et detruire des VM sur la fabric. Detient la voute du SITE, chiffree, et n'entre JAMAIS chez un tenant — reserve a l'ecosysteme de l'hebergeur |
|
||||||
| Resolution | `serveur_resolveur`, `client_resolveur` | UN resolveur recursif par tenant (Unbound), qui recurse depuis la racine et delegue la zone souveraine a PowerDNS. Remplace les N demons locaux d'avant le 2026-08-24 |
|
| Resolution | `serveur_resolveur`, `client_resolveur` | UN resolveur recursif par tenant (Unbound), qui recurse depuis la racine et delegue la zone souveraine a PowerDNS. Remplace les N demons locaux d'avant le 2026-08-24 |
|
||||||
|
| Cache du site | `serveur_artefacts_site` | designe LE cache que les ecosystemes voisins prennent comme amont : Debian telecharge une fois pour toute la fabric, et le cache ne voit que des requetes agregees. Reserve a l'ecosysteme de l'hebergeur |
|
||||||
| Agents de flotte | `client_metrique`, `client_journal`, `client_smtp` | collecte et relais sur toute la flotte |
|
| Agents de flotte | `client_metrique`, `client_journal`, `client_smtp` | collecte et relais sur toute la flotte |
|
||||||
|
|
||||||
*Rôles retirés (2026-07-04, supersédés ou hors conception)* : `serveur_sendmail`
|
*Rôles retirés (2026-07-04, supersédés ou hors conception)* : `serveur_sendmail`
|
||||||
|
|
|
||||||
|
|
@ -16,3 +16,15 @@ flux:
|
||||||
pair: externe
|
pair: externe
|
||||||
chiffrement: clair
|
chiffrement: clair
|
||||||
raison: "Remplir le cache depuis les dépôts Debian amont (deb.debian.org, security)."
|
raison: "Remplir le cache depuis les dépôts Debian amont (deb.debian.org, security)."
|
||||||
|
# LE CHAINAGE, cote consommateur. Un seul port, et seulement vers un CACHE — jamais
|
||||||
|
# d'une VM vers le cache d'un autre tenant.
|
||||||
|
#
|
||||||
|
# L'INGRESS CORRESPONDANT N'EST PAS ICI : il appartient a `serveur_artefacts_site`, le
|
||||||
|
# cache designe du site. Sans cette separation, chaque cache aurait accepte chaque
|
||||||
|
# autre — un maillage complet, visible au devis du 2026-08-24.
|
||||||
|
- sens: egress
|
||||||
|
port: 3142
|
||||||
|
protocole: tcp
|
||||||
|
pair: voisins_site
|
||||||
|
chiffrement: clair
|
||||||
|
raison: "Prendre le cache du site comme amont, plutot que d'aller chez Debian."
|
||||||
|
|
|
||||||
56
roles/serveur_artefacts_site/README.md
Normal file
56
roles/serveur_artefacts_site/README.md
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
# serveur_artefacts_site
|
||||||
|
|
||||||
|
**Le cache d'artefacts du SITE** : celui que les écosystèmes voisins prennent comme amont,
|
||||||
|
pour que Debian ne soit téléchargé qu'une fois pour toute la fabric.
|
||||||
|
|
||||||
|
## Le chaînage
|
||||||
|
|
||||||
|
```
|
||||||
|
VM du tenant → cache du tenant → cache du SITE → Debian
|
||||||
|
```
|
||||||
|
|
||||||
|
Chaque écosystème **garde le sien** — il reste maître de ses paquets et s'en émancipe d'un
|
||||||
|
drapeau — mais il ne va plus chercher chez Debian.
|
||||||
|
|
||||||
|
**Un cache unique où toutes les VM taperaient** aurait demandé un flux de chaque machine
|
||||||
|
de chaque tenant vers un hôte d'un autre tenant : N×M chemins à travers le default-deny.
|
||||||
|
Avec le chaînage il n'y en a **qu'un par écosystème**, entre deux caches.
|
||||||
|
|
||||||
|
Et l'étanchéité y gagne : le cache du site ne voit que des requêtes **agrégées**, jamais
|
||||||
|
quelle machine installe quoi.
|
||||||
|
|
||||||
|
## Pourquoi deux rôles plutôt qu'un drapeau
|
||||||
|
|
||||||
|
Les flux se déclarent dans `meta/flux.yml`, qui est **statique**. Un rôle unique aurait dû
|
||||||
|
déclarer l'ingress inter-tenant pour **tous** les caches — et le devis l'a montré :
|
||||||
|
|
||||||
|
```
|
||||||
|
+ TENANT_PATI29 -> CHEZ17_SERVEUR_ARTEFACTS un maillage complet,
|
||||||
|
+ TENANT_TECH23 -> CHEZ17_SERVEUR_ARTEFACTS chaque cache acceptant chaque autre
|
||||||
|
```
|
||||||
|
|
||||||
|
Avec la séparation, l'ingress n'existe qu'ici, et un seul cache est joignable.
|
||||||
|
|
||||||
|
## Qui peut le déclarer
|
||||||
|
|
||||||
|
**L'écosystème de l'hébergeur**, celui qui exploite la fabric. Un tenant ordinaire qui le
|
||||||
|
déclarerait s'offrirait à servir ses voisins sans y être invité.
|
||||||
|
|
||||||
|
C'est le même patron que `serveur_ops_site` : le **runner de site** prépare le terrain —
|
||||||
|
VNets, routes, flux — pour que les plans des tenants tiennent. Aucun écosystème n'ouvre de
|
||||||
|
porte chez un autre ; c'est le site qui autorise.
|
||||||
|
|
||||||
|
## Ce qu'il vérifie
|
||||||
|
|
||||||
|
**Qu'il ne se chaîne pas lui-même.** Il est le bout de la chaîne : le laisser pointer sur
|
||||||
|
un amont ferait tourner les paquets en rond entre deux caches, ou les ferait sortir du site
|
||||||
|
sans que personne ne l'ait décidé.
|
||||||
|
|
||||||
|
**Que le cache écoute vraiment.** Le rôle n'installe rien : sa seule prise sur le réel est
|
||||||
|
de vérifier que le service qu'il désigne existe. Sans ça, il attribuerait une
|
||||||
|
responsabilité à un port que personne n'écoute.
|
||||||
|
|
||||||
|
## Ce que ce rôle ne fait pas
|
||||||
|
|
||||||
|
Il n'installe ni ne configure apt-cacher-ng — c'est `serveur_artefacts`. Il **attribue une
|
||||||
|
responsabilité** et la rend lisible dans le plan.
|
||||||
17
roles/serveur_artefacts_site/defaults/main.yml
Normal file
17
roles/serveur_artefacts_site/defaults/main.yml
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
---
|
||||||
|
# LE CACHE D'ARTEFACTS DU SITE — celui que les autres écosystèmes prennent comme amont.
|
||||||
|
#
|
||||||
|
# Même patron que `serveur_ops_site` : le rôle n'installe rien de plus, il **attribue une
|
||||||
|
# responsabilité** et la rend lisible dans le plan. `serveur_artefacts` fait le travail ;
|
||||||
|
# celui-ci déclare que ce cache-là sert au-delà de son propre écosystème.
|
||||||
|
#
|
||||||
|
# POURQUOI DEUX RÔLES PLUTÔT QU'UN DRAPEAU. Les flux se déclarent dans `meta/flux.yml`,
|
||||||
|
# qui est STATIQUE : un rôle unique aurait dû déclarer l'ingress inter-tenant pour TOUS
|
||||||
|
# les caches. Le devis obtenu le montrait — un maillage complet où chaque cache acceptait
|
||||||
|
# chaque autre, alors qu'un seul doit être joignable.
|
||||||
|
#
|
||||||
|
# QUI PEUT LE DÉCLARER : l'écosystème de l'hébergeur, celui qui exploite la fabric. Un
|
||||||
|
# tenant ordinaire qui le déclarerait s'offrirait à servir ses voisins sans y être invité.
|
||||||
|
#
|
||||||
|
# Le cache du site va DIRECTEMENT chez Debian : il est le bout de la chaîne.
|
||||||
|
serveur_artefacts_site_amont_attendu: ""
|
||||||
12
roles/serveur_artefacts_site/meta/authentification.yml
Normal file
12
roles/serveur_artefacts_site/meta/authentification.yml
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
---
|
||||||
|
# Position de ce role dans la directive d'authentification (D-38..D-41).
|
||||||
|
# Voir docs/authentification.md. Gardee par la preuve P29.
|
||||||
|
authentification:
|
||||||
|
portee: sans-auth-humaine
|
||||||
|
mecanisme: aucun
|
||||||
|
formulaire_local: sans-objet
|
||||||
|
secours: "Acces SSH a l'hote"
|
||||||
|
raison: >-
|
||||||
|
Un cache de paquets ne sert que des machines. Ce qui le protege n'est pas une
|
||||||
|
authentification mais la LISTE de ses pairs : seuls les tenants de ce site le
|
||||||
|
joignent, et la frontiere le fait respecter. Ce qu'il sert est public par nature.
|
||||||
7
roles/serveur_artefacts_site/meta/empreinte.yml
Normal file
7
roles/serveur_artefacts_site/meta/empreinte.yml
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
---
|
||||||
|
# Empreinte ressources — ce role n'installe rien. Il attribue une responsabilite a un
|
||||||
|
# cache qui existe deja, et la rend lisible dans le plan.
|
||||||
|
setops_empreinte:
|
||||||
|
coeurs: 0
|
||||||
|
memoire_mo: 0
|
||||||
|
disque_go: 0
|
||||||
22
roles/serveur_artefacts_site/meta/flux.yml
Normal file
22
roles/serveur_artefacts_site/meta/flux.yml
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
---
|
||||||
|
# Flux réseau du cache d'artefacts DU SITE. Voir docs/flux-conception.md.
|
||||||
|
#
|
||||||
|
# UN SEUL FLUX, et c'est tout son sens : accepter les caches des écosystèmes voisins.
|
||||||
|
# `serveur_artefacts` porte le reste (servir sa propre flotte, remplir depuis Debian).
|
||||||
|
#
|
||||||
|
# `voisins_site` désigne les autres tenants que CE SITE héberge. Ni `flotte` (mon
|
||||||
|
# écosystème), ni `externe` — qui signifie « depuis l'Internet » et aurait publié le cache
|
||||||
|
# au monde entier.
|
||||||
|
#
|
||||||
|
# LA RÈGLE APPARTIENT AU SITE : c'est son runner qui prépare le terrain, pas un tenant qui
|
||||||
|
# ouvrirait une porte chez un autre.
|
||||||
|
flux:
|
||||||
|
- sens: ingress
|
||||||
|
port: 3142
|
||||||
|
protocole: tcp
|
||||||
|
pair: voisins_site
|
||||||
|
chiffrement: clair
|
||||||
|
raison: >-
|
||||||
|
Servir les caches des écosystèmes voisins. Debian n'est ainsi téléchargé qu'une
|
||||||
|
fois pour tout le site, et le cache ne voit que des requêtes AGRÉGÉES — jamais
|
||||||
|
quelle machine installe quoi.
|
||||||
23
roles/serveur_artefacts_site/tasks/main.yml
Normal file
23
roles/serveur_artefacts_site/tasks/main.yml
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
---
|
||||||
|
# UN CACHE DE SITE QUI SE CHAÎNERAIT SUR UN AUTRE SERAIT UNE BOUCLE.
|
||||||
|
#
|
||||||
|
# Il est le bout de la chaîne : les caches des tenants viennent à lui, et lui va chez
|
||||||
|
# Debian. Le laisser pointer sur un amont ferait tourner les paquets en rond entre deux
|
||||||
|
# caches, ou pire, hors du site sans que personne ne l'ait décidé.
|
||||||
|
- name: Exiger que le cache du site aille directement à l'amont
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- (serveur_artefacts_amont | default('')) == serveur_artefacts_site_amont_attendu
|
||||||
|
fail_msg: >-
|
||||||
|
Ce cache est déclaré cache du SITE : il doit aller directement chez Debian.
|
||||||
|
`serveur_artefacts_amont` doit rester vide — sinon les caches se chaînent en boucle.
|
||||||
|
|
||||||
|
# ÉCRIRE, PUIS RELIRE (D-68). Le rôle n'installe rien : sa seule prise sur le réel est de
|
||||||
|
# vérifier que le service qu'il désigne existe vraiment. Sans ça, il attribuerait une
|
||||||
|
# responsabilité à un port que personne n'écoute.
|
||||||
|
- name: Le cache écoute-t-il vraiment ?
|
||||||
|
ansible.builtin.wait_for:
|
||||||
|
host: "127.0.0.1"
|
||||||
|
port: "{{ serveur_artefacts_port }}"
|
||||||
|
timeout: 30
|
||||||
|
when: not ansible_check_mode
|
||||||
|
|
@ -477,6 +477,16 @@ def construire(tenants: list[tuple[str, str, dict]]) -> dict:
|
||||||
portees = [("any", if_wan)]
|
portees = [("any", if_wan)]
|
||||||
if admin_par_if[etiquette]["gestion"] and fl.get("poste", True):
|
if admin_par_if[etiquette]["gestion"] and fl.get("poste", True):
|
||||||
portees.append((f"SETOPS_ADMIN_{etiquette}_GESTION", if_gestion))
|
portees.append((f"SETOPS_ADMIN_{etiquette}_GESTION", if_gestion))
|
||||||
|
elif "voisins_site" in _pairs(fl):
|
||||||
|
# SORTANT VERS UN VOISIN : la destination est NOMMEE, pas « tout sauf
|
||||||
|
# l'interne ». Rendre `!SETOPS_INTERNES` ici aurait ouvert le port vers
|
||||||
|
# l'INTERNET — mesure du 2026-08-24, visible au devis avant application.
|
||||||
|
#
|
||||||
|
# Une regle par voisin : une regle porte une destination.
|
||||||
|
portees = [
|
||||||
|
(f"SETOPS_TENANT_{p2}{n2['index']}", if_transit)
|
||||||
|
for nom2, p2, n2 in tenants if nom2 != nom
|
||||||
|
]
|
||||||
else:
|
else:
|
||||||
portees = [("any", if_transit)]
|
portees = [("any", if_transit)]
|
||||||
for source, interface in portees:
|
for source, interface in portees:
|
||||||
|
|
@ -489,7 +499,11 @@ def construire(tenants: list[tuple[str, str, dict]]) -> dict:
|
||||||
# lui-meme pour qu'il apparaisse dans l'identite de la regle — sans
|
# lui-meme pour qu'il apparaisse dans l'identite de la regle — sans
|
||||||
# quoi la version niee et la version ouverte auraient la meme cle et
|
# quoi la version niee et la version ouverte auraient la meme cle et
|
||||||
# la seconde ne remplacerait jamais la premiere.
|
# la seconde ne remplacerait jamais la premiere.
|
||||||
"destination": destination if entrant else "!SETOPS_INTERNES",
|
# Sortant vers un voisin : la destination est le voisin lui-meme,
|
||||||
|
# portee par `source` puisque `portees` la transporte. Sortant vers
|
||||||
|
# l'Internet : « tout sauf l'interne ».
|
||||||
|
"destination": destination if entrant
|
||||||
|
else (source if "voisins_site" in _pairs(fl) else "!SETOPS_INTERNES"),
|
||||||
"ports": _ports(fl),
|
"ports": _ports(fl),
|
||||||
"chiffrement": fl.get("chiffrement"),
|
"chiffrement": fl.get("chiffrement"),
|
||||||
"role": role,
|
"role": role,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue