pools nommes comme les depots, et les cles sortent du poste
LE NOM D UN POOL EST CELUI DE SON DEPOT. Chezlepro-17 devient OPS-Chezlepro : le seed se lisait dans le nom, ce qui obligeait a connaitre le codage — et surtout le nom CHANGEAIT si l index changeait, ce que la renumerotation du site a montre le jour meme. Site-OPS ne derive de rien, et c est le point : les machines du genome ne dependent d aucun index, elles sont l infrastructure SUR laquelle les index vivent. Sans ce bloc elles restaient hors de tout pool. P69 — l amorcage d un tenant designe-t-il le site REEL ? dns_amorcage et artefacts_amorcage sont ecrits a la main, volontairement : au moment ou ils servent la machine ne resout aucun nom. Mais ils designent des machines DU SITE, et n ont pas suivi son renumerotage. La reconstruction du locataire s est arretee sur Failed to update apt cache, a quinze couches de sa cause. La preuve ne juge que les valeurs qui PRETENDENT designer le site : viser 9.9.9.9 est un choix, pas un oubli. LES CLES SORTENT DU POSTE, EN CLAIR, ET C EST RAISONNE. Support perdu : LUKS s en charge. Poste compromis : la seconde couche n aide pas, les originaux sont dans ~/.config sur ce meme poste. Elle coutait une phrase de passe stockee nulle part — le seul point que la procedure ne couvre pas. Option --support-chiffre explicite ; le defaut reste GPG, parce qu un support non chiffre est le cas le plus frequent. Et ma note qui disait les cles sorties depuis le 5 septembre etait fausse : le support ne portait que le depot hors site du 1er. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
This commit is contained in:
parent
b9b0d87db2
commit
56d202a8bb
8 changed files with 229 additions and 11 deletions
|
|
@ -188,7 +188,7 @@ Si `ansible-lint` n’est pas disponible, le signaler clairement. Ne pas invente
|
|||
## Écrire, puis relire (D-68)
|
||||
|
||||
`--syntax-check` et `ansible-lint` prouvent que le dépôt est cohérent **avec lui-même**.
|
||||
C'est aussi ce que font les 68 preuves de `make prouver` : elles lisent le dépôt, sans le
|
||||
C'est aussi ce que font les 69 preuves de `make prouver` : elles lisent le dépôt, sans le
|
||||
moindre appel réseau. **Aucune ne demande au système déployé s'il ressemble à ce que le
|
||||
dépôt annonce.**
|
||||
|
||||
|
|
|
|||
54
CHANGELOG.md
54
CHANGELOG.md
|
|
@ -1,5 +1,59 @@
|
|||
# CHANGELOG — Set-OPS
|
||||
|
||||
## 2026-09-12 (4) — Pools nommes comme les depots, et les cles sortent du poste
|
||||
|
||||
### Le nom d'un pool est celui de son depot
|
||||
|
||||
`Chezlepro-17` devient `OPS-Chezlepro`. Le seed se lisait dans le nom, ce qui etait juste
|
||||
mais obligeait a connaitre le codage — et surtout **le nom CHANGEAIT si l'index changeait** :
|
||||
la renumerotation du site l'a montre le jour meme. Ce qu'on lit dans la console est
|
||||
desormais ce qu'on tape dans un terminal.
|
||||
|
||||
L'unicite ne vient plus de l'index mais du nom de dossier, deja unique par construction.
|
||||
|
||||
**`Site-OPS` ne derive de rien, et c'est le point.** Les machines du genome — cache, forge,
|
||||
AC, noms, depot, supervision — ne dependent d'aucun index : elles sont l'infrastructure SUR
|
||||
laquelle les index vivent. Un nom invariable dit cela, et il reste le meme d'un hebergeur a
|
||||
l'autre. Sans ce bloc, les sept restaient hors de tout pool : sept orphelines a cote de
|
||||
trois flottes rangees.
|
||||
|
||||
CONFORME : 4 pool(s) Proxmox, 41 VM placee(s), aucun nom ni VMID en collision.
|
||||
|
||||
### P69 — l'amorcage d'un tenant designe-t-il le site REEL ?
|
||||
|
||||
`dns_amorcage` et `artefacts_amorcage` sont ecrits A LA MAIN dans les intrants d'un tenant,
|
||||
et c'est voulu : au moment ou ils servent, la premiere machine ne resout aucun nom. Une
|
||||
adresse, pas un nom.
|
||||
|
||||
Mais ces adresses designent des machines DU SITE. Le site a change d'index ; elles n'ont
|
||||
pas suivi. La reconstruction du locataire s'est arretee sur `infra-pki-01` avec
|
||||
« Failed to update apt cache » — a quinze couches de sa cause.
|
||||
|
||||
La preuve ne juge que les valeurs qui PRETENDENT designer le site : un tenant peut
|
||||
legitimement s'amorcer sur un resolveur public, et `OPS-Technolibre` comme `OPS-Patient0`
|
||||
visent `9.9.9.9`. C'est un choix, pas un oubli.
|
||||
|
||||
### Les cles sortent du poste, en clair, et c'est raisonne
|
||||
|
||||
Les neuf fichiers (1 644 o) sont sur la cle USB LUKS. **En tar clair**, par
|
||||
`--support-chiffre`, option ajoutee ce jour et explicite — le defaut reste GPG.
|
||||
|
||||
Deux menaces, deux reponses :
|
||||
|
||||
le support est perdu ou vole -> LUKS s'en charge
|
||||
le poste est compromis -> la 2e couche n'aide pas : les originaux sont
|
||||
dans ~/.config sur ce meme poste
|
||||
|
||||
La couche GPG n'ajoutait donc presque rien, et coutait une phrase de passe STOCKEE NULLE
|
||||
PART — le seul point que la procedure elle-meme ne couvre pas. On echangeait un risque de
|
||||
divulgation deja couvert contre un risque de PERTE qui ne l'etait pas.
|
||||
|
||||
Pourquoi ce n'est pas le defaut : un support non chiffre est le cas le plus frequent, et
|
||||
le silence ne doit jamais pencher du cote de la divulgation.
|
||||
|
||||
**Et la note qui disait les cles sorties depuis le 2026-09-05 etait fausse** : le support
|
||||
ne portait que le depot hors site du 1er. Verifie avant d'ecrire, pas apres.
|
||||
|
||||
## 2026-09-12 (3) — Trois reconstructions : trouver, verifier, prouver
|
||||
|
||||
La premiere reconstruction avait trouve seize defauts. Deux tours de plus ont ete faits, et
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
> [`docs/audit/affirmations.md`](affirmations.md).
|
||||
|
||||
- **Instance** : `/home/danallaire/Espace Chezlepro/DépôtsSurForge/Set-OPS-public/instance` — inventaire `/home/danallaire/Espace Chezlepro/DépôtsSurForge/Set-OPS-public/instance/inventories/principal/hosts.yml`
|
||||
- **Verdict** : ✅ CONFORME (67 OK · 0 echec · 1 saute)
|
||||
- **Verdict** : ✅ CONFORME (68 OK · 0 echec · 1 saute)
|
||||
|
||||
## Preuves
|
||||
|
||||
|
|
@ -40,7 +40,7 @@
|
|||
| P25 | Pare-feu Proxmox : est-ouest intra-tenant derive | AFF-107 | ✅ OK | CONFORME : pare-feu Proxmox, 3 tenant(s), 49 groupe(s), 87 regle(s). |
|
||||
| P26 | Integrations universelles : aucun hote laisse de cote | AFF-108 | ✅ OK | 14 hote(s) x 6 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. |
|
||||
| P28 | Pools Proxmox : un par tenant, sans collision | AFF-110 | ✅ OK | CONFORME : 3 pool(s) Proxmox, 34 VM placee(s), aucun nom ni VMID en collision. |
|
||||
| P28 | Pools Proxmox : un par tenant, sans collision | AFF-110 | ✅ OK | CONFORME : 4 pool(s) Proxmox, 41 VM placee(s), aucun nom ni VMID en collision. |
|
||||
| P29 | Authentification : chaque role declare sa position | AFF-111 | ✅ OK | 33 role(s) serveur declares (interne-sans-auth 2, ldap-direct 2, sans-auth-humaine 22, 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 | 62 scripts expliques et atteignables, 119 cibles make documentees, 68 roles avec README. |
|
||||
|
|
@ -69,7 +69,7 @@
|
|||
| P54 | L'insemination ne reclame aucun secret du tenant | — | ✅ OK | 2 couche(s) d'insemination (serveur_debian, serveur_ops), 9 role(s) applique(s), aucun secret de tenant reclame. |
|
||||
| P55 | La cle du SITE ne nait que sur le runner d'un tenant | — | ✅ OK | 14 hote(s) : la cle du SITE ne nait que sur 1 runner(s) de tenant, celle du tenant sur 14. |
|
||||
| P56 | Gabarit minimal, et rien de retire n'est perdu | — | ✅ OK | Gabarit minimal : 4 role(s), tous indispensables au premier demarrage ; 14 role(s) retire(s), tous repris par le socle ou le durcissement. |
|
||||
| P57 | Comptes en prose : les chiffres du depot sur lui-meme | — | ✅ OK | Les comptes ecrits en prose correspondent a la mesure (68 preuves, 68 roles, 41 groupes). |
|
||||
| P57 | Comptes en prose : les chiffres du depot sur lui-meme | — | ✅ OK | Les comptes ecrits en prose correspondent a la mesure (69 preuves, 68 roles, 41 groupes). |
|
||||
| P58 | Habilitations : chaque service dit a quel GROUPE, et par quoi | — | ✅ OK | 8 habilitation(s) declarees, toutes nommant un groupe, un mecanisme connu et une raison ; les `role-realm` sont projetees. |
|
||||
| P59 | Enumerations annoncees : le nombre correspond a ce qui suit | — | ✅ OK | 2 enumeration(s) annoncee(s) correspondent a ce qu'elles annoncent (formes non ambigues seulement). |
|
||||
| P60 | Wiki publie : la forge sert ce que le depot dit | AFF-002 | ✅ OK | Le wiki publie correspond au depot : `wiki/` n'a pas bouge depuis `904ece3` (publie le 2026-09-12). |
|
||||
|
|
@ -81,6 +81,7 @@
|
|||
| P66 | Clients OIDC : chaque URI vise un nom que le plan expose | — | ✅ OK | 4 client(s) OIDC, toutes leurs URI visent un FQDN que le plan expose (6 exposition(s)). |
|
||||
| P67 | Nom public : le service porte celui du plan, pas celui du role | — | ✅ OK | 6 service(s) expose(s) portent le nom du plan (6 groupe(s) derive(s)). |
|
||||
| P68 | Cle de depot telechargee : mesuree avant d'etre utilisee | — | ✅ OK | 5 role(s) telechargent une cle de depot, tous la mesurent avant de s'en servir. |
|
||||
| P69 | Amorcage d'un tenant : l'adresse designe le site REEL | — | ✅ OK | 2 adresse(s) d'amorcage designent bien une machine du site. |
|
||||
|
||||
## Couverture des affirmations ✅ du registre
|
||||
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ make placement-plan # chaque VM est-elle là où le plan la met
|
|||
|
||||
## Le trou qu'il comble
|
||||
|
||||
`scripts/prouver.py` porte 68 preuves (dont une conditionnelle, sautée sans la clé de la voûte). Elles sont toutes **statiques** : elles lisent le
|
||||
`scripts/prouver.py` porte 69 preuves (dont une conditionnelle, sautée sans la clé de la voûte). Elles sont toutes **statiques** : elles lisent le
|
||||
dépôt. Zéro appel réseau, zéro SSH, zéro `ansible`. Elles établissent que le dépôt est
|
||||
cohérent **avec lui-même** — que les handlers existent, que les intrants ont un
|
||||
propriétaire, que rien n'est codé en dur.
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ import yaml
|
|||
RACINE = Path(__file__).resolve().parents[1]
|
||||
sys.path.insert(0, str(RACINE / "scripts"))
|
||||
|
||||
from inventory_rules import (
|
||||
from inventory_rules import (POOL_SITE,
|
||||
instance_courante, # noqa: E402
|
||||
charger_serveurs,
|
||||
deriver_nomenclature,
|
||||
|
|
@ -172,6 +172,29 @@ def main(argv: list[str]) -> int:
|
|||
return 0
|
||||
|
||||
devis = construire(decouvrir())
|
||||
# LE SITE EST UN POOL AUSSI (2026-09-12). Les machines du genome — cache, forge, AC,
|
||||
# noms, depot, supervision — ne derivent d'aucun index : elles sont l'infrastructure
|
||||
# SUR laquelle les index vivent. D'ou un nom invariable, `Site-OPS`, identique d'un
|
||||
# hebergeur a l'autre.
|
||||
#
|
||||
# Sans ce bloc, elles restaient hors de tout pool : dans la console, sept machines
|
||||
# sans appartenance a cote de trois flottes rangees — exactement le desordre que le
|
||||
# reste du devis supprime.
|
||||
try:
|
||||
import underlay as _u
|
||||
_plan = (_u.lire_plan_site("serveurs.yml") or {}).get("serveurs") or {}
|
||||
_membres = sorted(
|
||||
({"nom": n, "vmid": int(v["vmid"]), "etat": str(v.get("etat", "actif"))}
|
||||
for n, v in _plan.items() if str(v.get("vmid", "")).strip().isdigit()),
|
||||
key=lambda m: m["vmid"])
|
||||
if _membres:
|
||||
devis["pools"].insert(0, {
|
||||
"pool": POOL_SITE, "tenant": "(site)", "index": None,
|
||||
"membres": _membres, "sans_vmid": [],
|
||||
})
|
||||
except Exception:
|
||||
pass # aucun underlay monte : le site n'existe pas de ce point de vue
|
||||
|
||||
if args.verifier:
|
||||
blocs = devis["pools"]
|
||||
if not blocs:
|
||||
|
|
|
|||
|
|
@ -174,6 +174,9 @@ def main() -> int:
|
|||
# phrase de passe et on ne risque pas d'ecraser ce qui est deja verifie.
|
||||
ap.add_argument("--compagnons", action="store_true",
|
||||
help="Deposer seulement le script de restauration et son mode d'emploi")
|
||||
ap.add_argument("--support-chiffre", action="store_true",
|
||||
help="le support est DEJA chiffre au repos (LUKS) : ecrire un tar "
|
||||
"clair plutot qu'une archive GPG (voir la note dans le code)")
|
||||
ap.add_argument("--nom", default="setops-cles",
|
||||
help="Nom de base de l'archive (defaut: setops-cles)")
|
||||
args = ap.parse_args()
|
||||
|
|
@ -220,6 +223,53 @@ def main() -> int:
|
|||
print(" RECENSEMENT SEUL — rien n'a ete ecrit.")
|
||||
return 0
|
||||
|
||||
# LE SUPPORT EST DEJA CHIFFRE : LA SECONDE COUCHE PROTEGE DE QUOI ? (2026-09-12)
|
||||
#
|
||||
# La question posee par l'exploitant, et elle se tient. Deux menaces, deux reponses :
|
||||
#
|
||||
# Le support est PERDU ou VOLE — LUKS s'en charge. Sans la phrase de deverrouillage
|
||||
# du volume, il n'y a rien a lire.
|
||||
#
|
||||
# Le POSTE est compromis — la seconde couche n'aide pas : les originaux sont dans
|
||||
# `~/.config` sur ce meme poste. Qui tient le poste tient deja les cles ; la copie
|
||||
# chiffree ne lui retire rien.
|
||||
#
|
||||
# La couche GPG n'ajoute donc presque rien, et coûte une phrase de passe STOCKEE
|
||||
# NULLE PART — que la procedure elle-meme designe comme le seul point non couvert :
|
||||
# perdue, l'archive est du bruit. On echange un risque de divulgation deja couvert
|
||||
# contre un risque de PERTE qui ne l'est pas.
|
||||
#
|
||||
# `--support-chiffre` est donc un choix legitime, mais il DOIT etre explicite : le
|
||||
# defaut reste l'archive GPG, parce qu'un support non chiffre est le cas le plus
|
||||
# frequent et que le silence ne doit jamais pencher du cote de la divulgation.
|
||||
if args.support_chiffre:
|
||||
archive = dest / f"{args.nom}-{os.uname().nodename}.tar"
|
||||
if archive.exists():
|
||||
raise SystemExit(
|
||||
f"REFUS : {archive} existe deja.\n"
|
||||
" On n'ecrase pas une sauvegarde de cles : elle est peut-etre la seule.\n"
|
||||
" La deplacer ou choisir un autre --nom.")
|
||||
with tarfile.open(archive, "w") as tar:
|
||||
for f, _ in fichiers:
|
||||
tar.add(f, arcname=f.name)
|
||||
archive.chmod(0o600)
|
||||
# RELIRE CE QU'ON VIENT D'ECRIRE, comme pour l'archive chiffree : une sauvegarde
|
||||
# qu'on n'a pas relue est une intention.
|
||||
with tarfile.open(archive, "r") as tar:
|
||||
noms = set(tar.getnames())
|
||||
manquants = [f.name for f, _ in fichiers if f.name not in noms]
|
||||
if manquants:
|
||||
archive.unlink(missing_ok=True)
|
||||
raise SystemExit(f"ECHEC de la relecture — archive SUPPRIMEE. "
|
||||
f"Manquent : {', '.join(manquants)}")
|
||||
print(f" Ecrit EN CLAIR dans l'archive : {archive}")
|
||||
print(f" {len(noms)} fichier(s) relus et retrouves.\n")
|
||||
print(" LA PROTECTION EST CELLE DU SUPPORT. Ce tar est lisible par quiconque")
|
||||
print(" monte ce volume deverrouille. Il n'a sa place que sur un support chiffre")
|
||||
print(" au repos, et le volume doit etre DEMONTE quand on ne s'en sert pas.")
|
||||
_deposer_compagnons(dest)
|
||||
return 0
|
||||
|
||||
archive = dest / f"{args.nom}-{os.uname().nodename}.tar.gpg"
|
||||
if archive.exists():
|
||||
raise SystemExit(
|
||||
|
|
|
|||
|
|
@ -312,12 +312,35 @@ def pool_de(nom_instance: str, index: int) -> str:
|
|||
justement la frontiere que Set-OPS etablit. La flotte derivee a donc ses propres
|
||||
pools, nommes comme tout le reste : depuis le seed.
|
||||
|
||||
`index` est deja garanti unique dans la federation par P21 : le nom l'est donc
|
||||
aussi, sans registre supplementaire. Forme : `Chezlepro-17`, `Technolibre-11`.
|
||||
LE NOM DU POOL EST CELUI DU DEPOT (2026-09-12, decision de l'exploitant). C'etait
|
||||
`Chezlepro-17` — le seed lu dans le nom. Juste, mais il obligeait a connaitre le
|
||||
codage pour relier un pool a son depot, et il CHANGEAIT si l'index changeait : la
|
||||
renumerotation du site l'a montre le jour meme.
|
||||
|
||||
Un pool porte desormais le nom du depot, tel quel : `OPS-Chezlepro`,
|
||||
`OPS-Technolibre`. Ce qu'on lit dans la console est ce qu'on tape dans un
|
||||
terminal, et un renumerotage ne renomme plus rien.
|
||||
|
||||
L'unicite ne vient plus de l'index mais du nom de dossier — qui est deja unique
|
||||
par construction, deux depots freres ne pouvant porter le meme. `index` reste au
|
||||
parametre : il ne sert plus au nom, il sert a refuser un appel incoherent.
|
||||
|
||||
Les pools `Env.Tenant` anterieurs a Set-OPS (`Prod.Chezlepro`, `Lab.KBR`...)
|
||||
restent l'ANCIEN MONDE : on n'y touche pas, et on n'y verse pas la flotte generee.
|
||||
"""
|
||||
base = re.sub(r"^OPS-", "", nom_instance)
|
||||
base = re.sub(r"[^A-Za-z0-9._-]", "", base) or "tenant"
|
||||
return f"{base}-{int(index)}"
|
||||
valider_index(index)
|
||||
base = re.sub(r"[^A-Za-z0-9._-]", "", nom_instance) or "tenant"
|
||||
return base
|
||||
|
||||
|
||||
# LE POOL DU SITE NE DERIVE DE RIEN, ET C'EST LE POINT (2026-09-12). Les machines du
|
||||
# genome — celles qui portent le cache, la forge, l'AC, les noms et le depot — ne
|
||||
# dependent d'aucun index : elles sont l'infrastructure SUR laquelle les index vivent.
|
||||
# Un nom invariable dit exactement cela, et il reste le meme d'un hebergeur a l'autre.
|
||||
#
|
||||
# A ne pas confondre avec le pool `Set-OPS` deja present sur le cluster de reference,
|
||||
# qui appartient a l'ancien monde.
|
||||
POOL_SITE = "Site-OPS"
|
||||
|
||||
|
||||
def est_groupe_operationnel(groupe: str) -> bool:
|
||||
|
|
|
|||
|
|
@ -3278,6 +3278,71 @@ def preuve_cle_telechargee_non_vide() -> tuple[bool, str]:
|
|||
f"avant de s'en servir.")
|
||||
|
||||
|
||||
def preuve_amorcage_suit_le_site() -> tuple[bool, str]:
|
||||
"""Les adresses d'amorcage d'un tenant designent-elles le site REEL ?
|
||||
|
||||
UNE SECONDE LISTE QUI SUIT UNE PREMIERE (2026-09-12). `dns_amorcage` et
|
||||
`artefacts_amorcage` sont ecrits A LA MAIN dans les intrants d'un tenant, et c'est
|
||||
voulu : au moment ou ils servent, la premiere machine du tenant ne resout aucun nom.
|
||||
Une adresse, pas un nom — la declaration le dit explicitement.
|
||||
|
||||
Mais ces adresses designent des machines DU SITE. Quand le site a pris son propre
|
||||
index et que ses zones sont passees de `10.0.3x` a `10.37.3x`, elles n'ont pas suivi :
|
||||
la reconstruction du locataire s'est arretee sur `infra-pki-01`, apt muet, avec un
|
||||
`resolv.conf` pointant une machine qui n'existait plus.
|
||||
|
||||
Le message ne disait pas « adresse perimee ». Il disait « Failed to update apt cache »,
|
||||
a quinze couches de sa cause.
|
||||
|
||||
CE QUE CETTE PREUVE NE FAIT PAS : juger une adresse qui ne designe pas le site. Un
|
||||
tenant peut legitimement s'amorcer sur un resolveur public — `OPS-Technolibre` et
|
||||
`OPS-Patient0` visent `9.9.9.9`, et c'est un choix, pas un oubli. On ne verifie que
|
||||
les valeurs qui PRETENDENT designer une machine du site : meme troisieme octet de
|
||||
zone, autre deuxieme octet. Une adresse etrangere au site n'est pas notre affaire.
|
||||
"""
|
||||
try:
|
||||
sys.path.insert(0, str(RACINE / "scripts"))
|
||||
import underlay as _u
|
||||
if not _u.charger():
|
||||
return True, "Aucun underlay monte : aucun site a suivre."
|
||||
attendus = {
|
||||
"dns_amorcage": _u.adresses_site_portant("serveur_resolveur"),
|
||||
"artefacts_amorcage": _u.adresses_site_portant("serveur_artefacts"),
|
||||
}
|
||||
except Exception as e:
|
||||
return True, f"Site illisible ({type(e).__name__}) : rien a comparer."
|
||||
if not any(attendus.values()):
|
||||
return True, "Le site ne porte ni resolveur ni cache : rien a suivre."
|
||||
|
||||
# Les troisiemes octets des zones du site — la signature d'une adresse « du site ».
|
||||
octets_site = {a.split(".")[2] for v in attendus.values() for a in v if a.count(".") == 3}
|
||||
|
||||
fautes, verifies = [], 0
|
||||
for intrants in sorted((RACINE.parent).glob("OPS-*/inventories/*/group_vars/all/10-intrants.yml")):
|
||||
try:
|
||||
d = yaml.safe_load(intrants.read_text(encoding="utf-8")) or {}
|
||||
except Exception:
|
||||
continue
|
||||
for cle, bons in attendus.items():
|
||||
brut = str(d.get(cle) or "").strip()
|
||||
if not brut or not bons:
|
||||
continue
|
||||
adr = brut.split(":")[0].split(",")[0].strip()
|
||||
if adr.count(".") != 3 or adr.split(".")[2] not in octets_site:
|
||||
continue # ne pretend pas designer le site : pas notre affaire
|
||||
verifies += 1
|
||||
if adr not in bons:
|
||||
fautes.append(f"{intrants.parents[3].name} : `{cle}` vise {adr}, "
|
||||
f"le site porte {', '.join(bons)}")
|
||||
if not verifies:
|
||||
return True, "Aucun tenant ne s'amorce sur une adresse du site."
|
||||
if fautes:
|
||||
return False, ("Adresse d'amorcage perimee — la premiere machine du tenant ne "
|
||||
"resoudra rien, et l'erreur parlera d'apt :\n - "
|
||||
+ "\n - ".join(fautes))
|
||||
return True, (f"{verifies} adresse(s) d'amorcage designent bien une machine du site.")
|
||||
|
||||
|
||||
PREUVES: list[dict] = [
|
||||
{"id": "P01", "titre": "Lint (ansible-lint)", "refs": ["AFF-006"],
|
||||
"cmds": [["ansible-lint", "-q"]]},
|
||||
|
|
@ -3434,6 +3499,8 @@ PREUVES: list[dict] = [
|
|||
"refs": [], "func": preuve_nom_public_vient_du_plan},
|
||||
{"id": "P68", "titre": "Cle de depot telechargee : mesuree avant d'etre utilisee",
|
||||
"refs": [], "func": preuve_cle_telechargee_non_vide},
|
||||
{"id": "P69", "titre": "Amorcage d'un tenant : l'adresse designe le site REEL",
|
||||
"refs": [], "func": preuve_amorcage_suit_le_site},
|
||||
]
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue