GUI : le rappel des secrets dérive de voute.py

`SECRETS_ATTENDUS` était une liste tenue à la main, en parallèle du
recensement que voute.py fait déjà depuis le plan, les rôles et les
group_vars. Deux sources pour la même vérité, et la manuelle avait divergé :
elle annonçait `vault_ldap_sssd`, que rien ne consomme — aucun rôle sssd
n'existe — et omettait `vault_step_ca_fingerprint`, réellement lu par
client_pki pour vérifier l'empreinte de l'AC racine.

Un opérateur qui suivait le panneau créait un secret inutile et en oubliait
un nécessaire.

Le rappel dérive maintenant de `voute.secrets_exiges()` — la même source que
la preuve P18 — augmentée de SECRETS_HORS_MOTIF pour les jetons Proxmox, qui
n'ont pas le préfixe `vault_`. Vérifié : 27 noms, écart nul avec le gabarit.
Dépôt public nu : liste vide plutôt qu'une erreur d'affichage.

Preuves : 24 OK, 0 échec.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Daniel Allaire 2026-08-01 22:25:41 -04:00
parent d00b60149d
commit 8bc8589163
2 changed files with 39 additions and 25 deletions

View file

@ -1,5 +1,24 @@
# CHANGELOG — Set-OPS
## 2026-08-01 (suite 13) — le rappel des secrets dérive de `voute.py`
`SECRETS_ATTENDUS` était une liste écrite à la main dans `inventory_gui.py`, en parallèle du
recensement que `scripts/voute.py` fait déjà depuis le plan, les rôles des groupes actifs et
les `group_vars`. Deux sources pour la même vérité, et la manuelle avait divergé :
| Clé | Panneau | Gabarit | Référencée |
|---|---|---|---|
| `vault_ldap_sssd` | annoncée | absente | **nulle part** — aucun rôle `sssd` n'existe |
| `vault_step_ca_fingerprint` | **omise** | présente | `roles/client_pki/defaults/main.yml:24` |
Un opérateur qui suivait le panneau créait donc un secret que rien ne consomme, et oubliait
celui dont `client_pki` a besoin pour vérifier l'empreinte de l'AC racine.
Le rappel dérive désormais de `voute.secrets_exiges()` — la **même source que la preuve
P18** — augmentée de `SECRETS_HORS_MOTIF` pour les jetons Proxmox, qui ne portent pas le
préfixe `vault_`. Vérifié : **27 noms, écart nul avec le gabarit**. Sur un dépôt public nu,
la liste est vide plutôt qu'en erreur.
## 2026-08-01 (suite 12) — la fabric se règle depuis la console
Tout le modèle d'underlay bâti aujourd'hui — routeur, spanning-tree, fabrics, transit —

View file

@ -145,30 +145,25 @@ INTRANTS_CLES_INTERDITES = {
"opnsense_api_key", "opnsense_api_secret",
}
# Rappel en lecture seule (jamais de valeur) : secrets a fournir via Ansible Vault.
SECRETS_ATTENDUS = [
# Accès Proxmox (voûte unique de l'instance : group_vars/all/vault.yml)
"proxmox_api_token_id", "proxmox_api_token_secret",
# PKI (step-ca)
"vault_step_ca_password", "vault_step_ca_provisioner_password",
# Identité (LDAP / Keycloak)
"vault_openldap_admin", "vault_ldap_sssd", "vault_keycloak_admin",
# Bases de données
"vault_postgresql_keycloak", "vault_bd_keycloak", "vault_bd_forgejo",
"vault_bd_icingadb", "vault_bd_nextcloud",
# Forge (Forgejo)
"vault_forgejo_admin", "vault_forgejo_secret_key", "vault_forgejo_internal_token",
# Observabilité / cache
"vault_grafana_admin", "vault_redis",
# Applications (admin)
"vault_nextcloud_admin",
# Secrets OIDC des clients SSO (un par app fédérée)
"vault_grafana_oidc", "vault_forgejo_oidc", "vault_icingaweb2_oidc",
"vault_nextcloud_oidc", "vault_oauth2_cookie",
# Sauvegarde (restic hors-nœud)
"vault_restic_password", "vault_backup_ssh_privkey",
# Frontière nord/sud (OPNsense) — API REST du pare-feu de bordure
"vault_opnsense_api_key", "vault_opnsense_api_secret",
]
def secrets_attendus() -> list[str]:
"""Noms des secrets a fournir par la voute — DERIVES, jamais tenus a la main.
`voute.secrets_exiges()` les recense depuis le plan, les roles des groupes actifs et
les group_vars de l'instance ; `voute.SECRETS_HORS_MOTIF` ajoute ceux qui ne portent
pas le prefixe `vault_` (les jetons Proxmox). C'est la MEME source que la preuve P18.
Une liste ecrite a la main vivait ici et avait diverge : elle annoncait
`vault_ldap_sssd`, que rien ne consomme, et omettait `vault_step_ca_fingerprint`,
reellement lu par `client_pki`. Un operateur qui suivait le panneau creait donc un
secret inutile et en oubliait un necessaire.
Depot public nu (aucune instance) : liste vide plutot qu'une erreur d'affichage.
"""
try:
import voute
return sorted(set(voute.secrets_exiges()) | voute.SECRETS_HORS_MOTIF)
except Exception:
return []
# Garde-fous des executions (verifier / deployer) depuis l'interface.
JETON = secrets.token_urlsafe(18)
@ -491,7 +486,7 @@ def intrants_api() -> dict:
return {
"schema": schema,
"valeurs": intrants_courants(),
"secrets_attendus": SECRETS_ATTENDUS,
"secrets_attendus": secrets_attendus(),
"fichiers": {k: os.path.relpath(v, RACINE) for k, v in FICHIERS_INTRANTS.items()},
}