Consolider les secrets dans une voûte unique par environnement
Fini les voûtes éparpillées : tous les secrets (token Proxmox + vault_*) vivent dans group_vars/all/vault.yml, un seul fichier chiffré, un seul mot de passe. Gabarit committé exemples/vault.exemple.yml (17 clés). make config écrit/édite cette voûte (semée depuis le gabarit si absente). .gitignore durci (**/vault.yml). Docs : config-proxmox.md (+ migration), intrants- communs.md §H, QUICKSTART. Le GUI ne stocke aucun secret. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
3a3a80e0ac
commit
c4e73f8712
7 changed files with 115 additions and 30 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -6,6 +6,7 @@ facts_cache/
|
|||
.ansible/
|
||||
*.vault
|
||||
*.vault.yml
|
||||
**/vault.yml
|
||||
*.secret
|
||||
*.pem
|
||||
*.key
|
||||
|
|
|
|||
10
CHANGELOG.md
10
CHANGELOG.md
|
|
@ -2,6 +2,16 @@
|
|||
|
||||
## 2026-06-30
|
||||
|
||||
### Modifié
|
||||
- **Voûte de secrets unique par environnement.** Fini les voûtes éparpillées : tous
|
||||
les secrets de l'instance (token Proxmox + 17 `vault_*` pour PKI, LDAP/SSO, bases,
|
||||
forge, observabilité) vivent dans **un seul fichier chiffré**,
|
||||
`inventories/<env>/group_vars/all/vault.yml`. Gabarit committé
|
||||
`exemples/vault.exemple.yml`. `make config` (`config_proxmox.py`) écrit/édite
|
||||
désormais cette voûte (semée depuis le gabarit si absente). `.gitignore` durci
|
||||
(`**/vault.yml`). Docs mises à jour (config-proxmox.md avec étapes de migration,
|
||||
intrants-communs.md §H, QUICKSTART). Le GUI ne stocke toujours aucun secret.
|
||||
|
||||
### Corrigé
|
||||
- **`chezlepro_timezone` n'était appliqué nulle part.** Cet intrant de base global
|
||||
était défini mais aucun rôle ne s'en servait. Le rôle `chrony` (appliqué à tout
|
||||
|
|
|
|||
|
|
@ -44,9 +44,10 @@ Tu peux aussi le faire dans le GUI plus tard (`make inventaire-ui`).
|
|||
make config # renseigne API host/user/port, nœud, stockage, VMID du template...
|
||||
```
|
||||
Chaque paramètre demandé est expliqué dans [`docs/config-proxmox.md`](docs/config-proxmox.md).
|
||||
Place ton **token API** et tes secrets dans le Vault de l'instance
|
||||
(`instance/inventories/lab/group_vars/proxmox.vault.yml`, à partir du `.example`,
|
||||
chiffré avec `ansible-vault`). Exporte ton mot de passe Vault, ex. :
|
||||
Tous tes secrets (token API + `vault_*`) vont dans **une voûte unique par
|
||||
environnement** : `instance/inventories/lab/group_vars/all/vault.yml`, à partir du
|
||||
gabarit [`exemples/vault.exemple.yml`](exemples/vault.exemple.yml), chiffrée avec
|
||||
`ansible-vault`. Exporte ton mot de passe Vault, ex. :
|
||||
```bash
|
||||
export ANSIBLE_VAULT_PASSWORD_FILE=~/.config/setops-vault-pass
|
||||
```
|
||||
|
|
|
|||
|
|
@ -5,8 +5,9 @@ la connexion au cluster Proxmox et les valeurs de clonage par défaut. Il pose
|
|||
**16 paramètres non sensibles** puis propose de saisir les **secrets API**.
|
||||
|
||||
- Non sensibles → `instance/inventories/lab/group_vars/proxmox.yml`
|
||||
- Secrets API → `instance/inventories/lab/group_vars/proxmox.vault.yml` (chiffré
|
||||
par `ansible-vault`)
|
||||
- Secrets → **voûte unique** `instance/inventories/lab/group_vars/all/vault.yml`
|
||||
(chiffrée par `ansible-vault`), qui contient **tous** les secrets de l'instance
|
||||
(token Proxmox + `vault_*`). Voir [§4](#4-secrets-de-linstance-).
|
||||
|
||||
À chaque invite, la valeur courante (ou le défaut) est affichée entre crochets :
|
||||
**appuyer sur Entrée conserve cette valeur**. On peut donc relancer `make config`
|
||||
|
|
@ -56,20 +57,41 @@ Ces valeurs s'appliquent à toute VM clonée, **sauf** si l'hôte les surcharge
|
|||
| Pare-feu interface Proxmox | `proxmox_clone_parefeu_interface` | `non` | Active le pare-feu Proxmox **au niveau de la NIC**. Laisser `non` : le filtrage se fait dans l'invité (nftables), pas chez l'hyperviseur. |
|
||||
| Démarrer le clone après création | `proxmox_clone_demarrer` | `oui` | `oui` = booter la VM dès la création (nécessaire pour qu'Ansible la joigne ensuite). |
|
||||
|
||||
## 4. Secrets API Proxmox 🔒 *(constantes, chiffrées)*
|
||||
## 4. Secrets de l'instance 🔒 *(voûte unique)*
|
||||
|
||||
L'assistant demande ensuite : « Configurer les secrets API Proxmox maintenant ».
|
||||
Si `oui` :
|
||||
Tous les secrets de l'instance vivent dans **une seule voûte chiffrée par
|
||||
environnement** : `instance/inventories/<env>/group_vars/all/vault.yml`. Un seul
|
||||
fichier, un seul mot de passe — fini les voûtes éparpillées. Gabarit committé :
|
||||
[`exemples/vault.exemple.yml`](../exemples/vault.exemple.yml) (token Proxmox +
|
||||
17 clés `vault_*` pour PKI, LDAP/SSO, bases, forge, observabilité).
|
||||
|
||||
L'assistant demande « Configurer la voûte de secrets maintenant ». Si `oui` :
|
||||
|
||||
| Invite | Variable | Défaut | Sens / quoi saisir |
|
||||
| --- | --- | --- | --- |
|
||||
| Token ID Proxmox | `proxmox_api_token_id` | `set-ops` | Identifiant du **token API** créé côté Proxmox pour l'utilisateur API. |
|
||||
| Token secret Proxmox | `proxmox_api_token_secret` | *(aucun)* | Secret du token. **Saisie masquée**, écrite uniquement dans le Vault chiffré. |
|
||||
| Token ID Proxmox | `proxmox_api_token_id` | `set-ops` | Identifiant du **token API** créé côté Proxmox. |
|
||||
| Token secret Proxmox | `proxmox_api_token_secret` | *(aucun)* | Secret du token. **Saisie masquée**, écrit dans la voûte chiffrée. |
|
||||
|
||||
- Si `proxmox.vault.yml` existe déjà, l'assistant ouvre directement
|
||||
`ansible-vault edit` (pas de re-saisie en clair).
|
||||
- Un secret vide ⇒ le Vault **n'est pas créé**.
|
||||
- Ces deux clés ne transitent **jamais** par le GUI ni par aucun fichier en clair.
|
||||
- Si la voûte **existe déjà**, l'assistant ouvre directement `ansible-vault edit`
|
||||
(aucune re-saisie en clair).
|
||||
- Si elle **n'existe pas**, l'assistant la **sème depuis le gabarit** (toutes les
|
||||
clés présentes, vides), y place le token, puis la chiffre. On renseigne ensuite
|
||||
les autres secrets avec `ansible-vault edit …/all/vault.yml`.
|
||||
- Ces secrets ne transitent **jamais** par le GUI ni par aucun fichier en clair ;
|
||||
le GUI n'en affiche que les **noms** (panneau « Intrants »).
|
||||
|
||||
### Migration depuis l'ancienne `proxmox.vault.yml`
|
||||
|
||||
Si tu as déjà une `proxmox.vault.yml`, déplace son contenu dans la voûte unique :
|
||||
|
||||
```bash
|
||||
cd instance/inventories/lab/group_vars
|
||||
cp ../../../../exemples/vault.exemple.yml all/vault.yml
|
||||
ansible-vault view proxmox.vault.yml # relève token_id + secret
|
||||
ansible-vault edit all/vault.yml # colle-les, renseigne le reste
|
||||
ansible-vault encrypt all/vault.yml # si pas déjà chiffrée
|
||||
git rm --cached --ignore-unmatch proxmox.vault.yml 2>/dev/null; rm proxmox.vault.yml proxmox.vault.yml.example
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -48,7 +48,11 @@ journald (rétention) · core_dumps · systemd_ssh_auto.
|
|||
- Smallstep (step-cli) — `client_pki` ↔ `serveur_step_ca`.
|
||||
- Grafana (alloy/loki/grafana) — `client_journal` ↔ `serveur_loki`/`serveur_grafana`.
|
||||
|
||||
### H. Secrets Vault communs 🔒 — `proxmox.vault.yml` + vault d'instance
|
||||
### H. Secrets Vault communs 🔒 — **voûte unique** `group_vars/all/vault.yml`
|
||||
> Tous les secrets de l'instance dans **un seul fichier chiffré par environnement**
|
||||
> (`inventories/<env>/group_vars/all/vault.yml`), gabarit
|
||||
> [`exemples/vault.exemple.yml`](../exemples/vault.exemple.yml). Un mot de passe, un
|
||||
> endroit. Édité via `ansible-vault edit` (jamais par le GUI).
|
||||
`proxmox_api_token_id/secret`, `vault_step_ca_password`, `vault_step_ca_fingerprint`,
|
||||
`vault_step_ca_provisioner_password`, `vault_openldap_admin`, `vault_ldap_sssd`,
|
||||
`vault_keycloak_admin`, `vault_postgresql_keycloak`, `vault_bd_keycloak`,
|
||||
|
|
|
|||
43
exemples/vault.exemple.yml
Normal file
43
exemples/vault.exemple.yml
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
---
|
||||
# Voûte UNIQUE de l'instance — TOUS les secrets, un seul fichier, un seul mot de passe.
|
||||
#
|
||||
# Installation :
|
||||
# 1. Copier ce gabarit vers la voûte de chaque environnement :
|
||||
# cp exemples/vault.exemple.yml instance/inventories/lab/group_vars/all/vault.yml
|
||||
# 2. Renseigner les valeurs, puis chiffrer :
|
||||
# ansible-vault encrypt instance/inventories/lab/group_vars/all/vault.yml
|
||||
# 3. Éditer ensuite sans jamais déchiffrer sur disque :
|
||||
# ansible-vault edit instance/inventories/lab/group_vars/all/vault.yml
|
||||
#
|
||||
# Ne JAMAIS versionner le fichier vault.yml (couvert par .gitignore).
|
||||
# Le GUI ne stocke ni n'affiche ces valeurs : il n'en montre que les NOMS
|
||||
# (panneau « Intrants de base »). Le mot de passe du vault est saisi au déploiement.
|
||||
|
||||
# --- Accès API Proxmox (clonage des VM) ---
|
||||
proxmox_api_token_id: ""
|
||||
proxmox_api_token_secret: ""
|
||||
|
||||
# --- AC / PKI interne (step-ca) ---
|
||||
vault_step_ca_password: ""
|
||||
vault_step_ca_fingerprint: ""
|
||||
vault_step_ca_provisioner_password: ""
|
||||
|
||||
# --- Identité (LDAP / SSO) ---
|
||||
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: ""
|
||||
|
||||
# --- Forge (Forgejo) ---
|
||||
vault_forgejo_admin: ""
|
||||
vault_forgejo_secret_key: ""
|
||||
vault_forgejo_internal_token: ""
|
||||
|
||||
# --- Observabilité / divers ---
|
||||
vault_grafana_admin: ""
|
||||
vault_redis: ""
|
||||
|
|
@ -15,7 +15,10 @@ import yaml
|
|||
RACINE = Path(__file__).resolve().parents[1]
|
||||
INSTANCE = Path(os.environ.get("SETOPS_INSTANCE") or (RACINE / "instance"))
|
||||
FICHIER_PROXMOX = INSTANCE / "inventories/lab/group_vars/proxmox.yml"
|
||||
FICHIER_VAULT = INSTANCE / "inventories/lab/group_vars/proxmox.vault.yml"
|
||||
# Voûte UNIQUE de l'environnement : tous les secrets (token Proxmox + vault_*) au
|
||||
# même endroit, un seul mot de passe. Gabarit : exemples/vault.exemple.yml.
|
||||
FICHIER_VAULT = INSTANCE / "inventories/lab/group_vars/all/vault.yml"
|
||||
GABARIT_VAULT = RACINE / "exemples/vault.exemple.yml"
|
||||
|
||||
|
||||
VALEURS_DEFAUT = {
|
||||
|
|
@ -73,7 +76,7 @@ def ecrire_yaml(path: Path, data: dict) -> None:
|
|||
with path.open("w", encoding="utf-8") as fichier:
|
||||
fichier.write("---\n")
|
||||
fichier.write("# Parametres non sensibles pour les operations Proxmox.\n")
|
||||
fichier.write("# Les secrets API doivent aller dans proxmox.vault.yml.\n\n")
|
||||
fichier.write("# Les secrets vont dans la voûte unique group_vars/all/vault.yml.\n\n")
|
||||
yaml.safe_dump(data, fichier, default_flow_style=False, sort_keys=False, allow_unicode=True)
|
||||
|
||||
|
||||
|
|
@ -119,35 +122,36 @@ def demander_oui_non(question: str, defaut: bool = False) -> bool:
|
|||
|
||||
|
||||
def configurer_vault() -> None:
|
||||
if not demander_oui_non("Configurer les secrets API Proxmox maintenant"):
|
||||
if not demander_oui_non("Configurer la voûte de secrets maintenant"):
|
||||
return
|
||||
|
||||
if FICHIER_VAULT.exists():
|
||||
print(f"Ouverture du Vault existant: {os.path.relpath(FICHIER_VAULT, RACINE)}")
|
||||
print(f"Ouverture de la voûte existante: {os.path.relpath(FICHIER_VAULT, RACINE)}")
|
||||
subprocess.run(["ansible-vault", "edit", str(FICHIER_VAULT)], check=True)
|
||||
return
|
||||
|
||||
# Voûte absente : on la sème à partir du gabarit (toutes les clés vides),
|
||||
# on y place le token Proxmox saisi, puis on chiffre. Les autres secrets se
|
||||
# renseignent ensuite via `ansible-vault edit`.
|
||||
token_id = input("Token ID Proxmox [set-ops] : ").strip() or "set-ops"
|
||||
token_secret = getpass("Token secret Proxmox : ").strip()
|
||||
if not token_secret:
|
||||
print("Secret vide: Vault non cree.")
|
||||
print("Secret vide: voûte non créée.")
|
||||
return
|
||||
|
||||
contenu = charger_yaml(GABARIT_VAULT)
|
||||
contenu["proxmox_api_token_id"] = token_id
|
||||
contenu["proxmox_api_token_secret"] = token_secret
|
||||
|
||||
FICHIER_VAULT.parent.mkdir(parents=True, exist_ok=True)
|
||||
try:
|
||||
fd = os.open(FICHIER_VAULT, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o600)
|
||||
with os.fdopen(fd, "w", encoding="utf-8") as fichier:
|
||||
yaml.safe_dump(
|
||||
{
|
||||
"proxmox_api_token_id": token_id,
|
||||
"proxmox_api_token_secret": token_secret,
|
||||
},
|
||||
fichier,
|
||||
default_flow_style=False,
|
||||
sort_keys=False,
|
||||
)
|
||||
yaml.safe_dump(contenu, fichier, default_flow_style=False, sort_keys=False, allow_unicode=True)
|
||||
subprocess.run(["ansible-vault", "encrypt", str(FICHIER_VAULT)], check=True)
|
||||
print(f"Vault cree: {os.path.relpath(FICHIER_VAULT, RACINE)}")
|
||||
print(f"Voûte créée: {os.path.relpath(FICHIER_VAULT, RACINE)}")
|
||||
print("Renseigne les autres secrets avec : ansible-vault edit "
|
||||
f"{os.path.relpath(FICHIER_VAULT, RACINE)}")
|
||||
except Exception:
|
||||
if FICHIER_VAULT.exists():
|
||||
FICHIER_VAULT.unlink()
|
||||
|
|
|
|||
Loading…
Reference in a new issue