diff --git a/docs/audit/preuve-2026-08-24.md b/docs/audit/preuve-2026-08-24.md index b2020af..380c77b 100644 --- a/docs/audit/preuve-2026-08-24.md +++ b/docs/audit/preuve-2026-08-24.md @@ -21,7 +21,7 @@ | 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). | | 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 : 34 rôles, 86 flux, schéma + matrice OK. | +| P09 | Flux reseau (schema + matrice) | AFF-071 | ✅ OK | Flux coherents : 34 rôles, 87 flux, schéma + matrice OK. | | 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 | | P12 | Existence des runbooks cites | AFF-010, AFF-011, AFF-012, AFF-083 | ✅ OK | 17/17 runbooks/registres cites presents. | @@ -36,7 +36,7 @@ | 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). | | 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, 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. | +| P24 | Frontiere nord/sud : acces d'administration declare | AFF-104 | ✅ OK | CONFORME : frontiere nord/sud, 68 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), 51 groupe(s), 80 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). | | 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. | @@ -44,7 +44,7 @@ | 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. | | 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 (122 cle(s) declaree(s) par l'instance). | +| P32 | Intrants exiges par les roles : tous fournis | — | ✅ OK | CONFORME : 37 exigence(s) de role, toutes satisfaites (125 cle(s) declaree(s) par l'instance). | | 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)). | | 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). | diff --git a/roles/serveur_ops/defaults/main.yml b/roles/serveur_ops/defaults/main.yml index 7689a19..a437e84 100644 --- a/roles/serveur_ops/defaults/main.yml +++ b/roles/serveur_ops/defaults/main.yml @@ -68,6 +68,21 @@ serveur_ops_forge_organisation: "genome" serveur_ops_forge_externe: false serveur_ops_forge_amont: "" +# --- LA CONFIANCE ENVERS UNE FORGE D'UN AUTRE TENANT ------------------------- +# +# Lire le genome chez un voisin suppose de faire confiance a SON autorite — or chaque +# ecosysteme a la sienne, et `client_pki` n'etablit la confiance que dans celle du tenant. +# +# ON NE POSE PAS CETTE RACINE DANS LE MAGASIN SYSTEME. L'y mettre ferait confiance a cette +# AC pour TOUT ce que la machine contacte, alors qu'on ne lui demande qu'une chose : servir +# un depot git. `git config http..sslCAInfo` limite la confiance a CETTE url — une +# porte, pas un trousseau. +# +# Chemin d'un certificat racine PUBLIC, sur le controleur. Vide = rien a poser (forge du +# meme ecosysteme, ou AC publiquement reconnue). +serveur_ops_forge_amont_ac: "" +serveur_ops_forge_amont_ac_depot: "{{ serveur_ops_racine }}/.ac-amont.crt" + # Les dépôts du génome, et où ils atterrissent. Les noms sont ceux que la forge porte # (minuscules) ; les destinations reprennent la disposition du poste du mainteneur, où # le moteur et les instances sont des dossiers frères — c'est cette fraternité que diff --git a/roles/serveur_ops/meta/flux.yml b/roles/serveur_ops/meta/flux.yml index 672ed2b..b6fc5b3 100644 --- a/roles/serveur_ops/meta/flux.yml +++ b/roles/serveur_ops/meta/flux.yml @@ -25,3 +25,15 @@ flux: pair: externe chiffrement: tls-requis raison: "API de l'hyperviseur : créer et cloner les VM d'un écosystème descendant." + # LIRE LE GENOME CHEZ UN VOISIN. La forge du genome se mutualise par SITE : le moteur, + # les modeles et la fabric sont le meme contenu pour tous les tenants. Seul le plan + # `OPS-xxx` differe. + # + # La forge DE TRAVAIL d'un ecosysteme -- celle qui sert ses gens -- reste un service du + # tenant, et n'a rien a voir avec ce flux. + - sens: egress + port: 443 + protocole: tcp + pair: voisins_site + chiffrement: tls-requis + raison: "Cloner le genome depuis la forge du site, quand cet ecosysteme n'heberge pas la sienne." diff --git a/roles/serveur_ops/tasks/main.yml b/roles/serveur_ops/tasks/main.yml index fac8d83..4d52405 100644 --- a/roles/serveur_ops/tasks/main.yml +++ b/roles/serveur_ops/tasks/main.yml @@ -68,14 +68,42 @@ delay: 6 until: serveur_ops_pip is succeeded +# LA CONFIANCE, AVANT LE CLONE — et limitee a une seule url. +# +# Voir defaults/main.yml : on ne pose pas cette racine dans le magasin systeme. `git +# config http..sslCAInfo` ne l'applique qu'aux echanges avec CETTE forge. +- name: Deposer la racine de la forge amont + ansible.builtin.copy: + src: "{{ serveur_ops_forge_amont_ac }}" + dest: "{{ serveur_ops_forge_amont_ac_depot }}" + owner: "{{ serveur_ops_utilisateur }}" + group: "{{ serveur_ops_utilisateur }}" + mode: "0644" + when: + - serveur_ops_forge_amont_ac | length > 0 + - not ansible_check_mode + +- name: Limiter la confiance a la forge amont, et a elle seule + community.general.git_config: + name: "http.{{ serveur_ops_forge_url }}/.sslCAInfo" + scope: global + value: "{{ serveur_ops_forge_amont_ac_depot }}" + become: true + become_user: "{{ serveur_ops_utilisateur }}" + when: + - serveur_ops_forge_amont_ac | length > 0 + - not ansible_check_mode + # --- LE GÉNOME, DEPUIS SA PROPRE FORGE --------------------------------------- # # Cloné en anonyme : les dépôts du génome sont lisibles sur la forge de l'écosystème, et # le poste n'a donc AUCUN justificatif à détenir pour se reconstruire. C'est délibéré — # un secret de moins sur la machine qui en concentre déjà beaucoup. # -# La confiance TLS vient de `client_pki` (racine step-ca dans le magasin système). Sans -# lui, `git clone` refuse le certificat de la forge — et c'est bien qu'il refuse. +# La confiance TLS vient de `client_pki` quand la forge est celle de CET écosystème +# (racine step-ca dans le magasin système). Quand elle est celle d'un voisin, elle vient +# de la tâche ci-dessus — limitée à cette seule url. Sans l'une ou l'autre, `git clone` +# refuse le certificat, et c'est bien qu'il refuse. - name: Cloner le génome depuis la forge de l'écosystème ansible.builtin.git: repo: "{{ serveur_ops_forge_url }}/{{ serveur_ops_forge_organisation }}/{{ item.depot }}.git"