Interface web : écarts, dry-run et synchronisation (phases 1 et 2) #1

Merged
claude Bot merged 8 commits from phase-1-ui into main 2026-10-13 16:47:35 +02:00

Avant : pve-confsync n'était qu'une CLI (check, export, diff, apply), configurée par un YAML.

Après : pve-confsync serve lance une interface web embarquée (Go embed, SQLite) dont l'ergonomie reprend celle de Logstream. On y voit une carte par cluster, puis les écarts du client choisi, avec le détail champ par champ : politique, référence, mapping, valeur actuelle et valeur après synchro. On peut lancer un dry-run puis synchroniser par objet, par client ou globalement. L'interface tient aussi un journal des exécutions et un audit. serve -demo démarre de faux clusters PVE pour l'essayer sans labo.

Comment

  • Stockage (internal/store) : SQLite en Go pur (modernc, CGO_ENABLED=0). On y garde les clusters, les paramètres, les utilisateurs, le journal et l'audit.
    • Les secrets des tokens sont chiffrés en AES-256-GCM. La clé est lue dans CONFSYNC_SECRET_KEY, sinon _FILE, sinon DATA_DIR/secret.key.
    • Les secrets ne sont jamais renvoyés au navigateur. L'export YAML les remplace par token_secret_env.
  • Serveur (internal/server) :
    • Authentification par comptes locaux (PBKDF2-SHA256, 600 000 itérations) et OIDC (code + PKCE, rôle déduit des groupes).
    • Trois rôles : admin, operator, viewer.
    • Sessions par cookie signé, invalidé au changement de mot de passe.
    • Protection CSRF : l'en-tête X-Confsync est exigé sur les écritures. La CSP n'autorise aucun script ni style en ligne.
  • Synchronisation :
    • Chaque dry-run est enregistré avec une empreinte du plan. L'apply recalcule le plan et répond 409 si l'empreinte a changé.
    • Les changements SDN demandent de taper le nom du client, ou celui de la référence pour une synchro globale.
    • Un seul apply tourne à la fois, en tâche de fond, et chaque étape est écrite dans le journal.
  • Sélection (engine.Filter) :
    • Sélectionner un objet ajoute ses dépendances : la zone et le vnet parents à créer, ou les enfants à supprimer d'abord.
    • Une erreur sur un parent reste bloquante quand on ne sélectionne que l'enfant.
  • UI (web/) : HTML, CSS et JS sans framework ni build. Elle est en français et en anglais, avec thème clair ou sombre et une mise en page mobile. Les paramètres couvrent les clusters (test d'accès, TLS, mapping et politiques par client), la synchronisation, les utilisateurs, l'import/export YAML, le compte et l'apparence.
  • Docker : CMD ["serve"] avec un healthcheck. Le compose a un service confsync-web et un service CLI sous le profil cli.

Tests

  • go vet et go test -race ./... passent. gofmt est propre et le build passe avec CGO_ENABLED=0.
  • Nouveaux tests :
    • engine/select_test.go : dépendances, ordre des suppressions, erreurs des parents, empreinte.
    • store/store_test.go : chiffrement, masquage des secrets, utilisateurs, dernier admin protégé.
    • server/server_test.go : rôles, CSRF, absence de secret dans les réponses, puis le parcours complet dry-run → refus (bloquant, confirmation, empreinte périmée) → apply → client conforme.
  • Parcours manuel en Chromium (Playwright) sur le mode démo : aucune erreur JS.

Limites connues

  • Pas testé sur de vrais clusters PVE, seulement sur le faux serveur.
  • La synchro globale est bloquée dès qu'un client a une erreur ou est illisible. C'est un choix prudent.
  • Auth.CheckProvider existe mais n'est pas appelé au démarrage dans serve.go.
  • clientIP fait confiance à X-Forwarded-For (comme Logstream), à restreindre si le service est exposé sans reverse proxy.

🤖 Generated with Claude Code

https://claude.ai/code/session_015a8P6WMRPeqdpd5VCh6jAy

Avant : pve-confsync n'était qu'une CLI (check, export, diff, apply), configurée par un YAML. Après : `pve-confsync serve` lance une interface web embarquée (Go embed, SQLite) dont l'ergonomie reprend celle de Logstream. On y voit une carte par cluster, puis les écarts du client choisi, avec le détail champ par champ : politique, référence, mapping, valeur actuelle et valeur après synchro. On peut lancer un dry-run puis synchroniser par objet, par client ou globalement. L'interface tient aussi un journal des exécutions et un audit. `serve -demo` démarre de faux clusters PVE pour l'essayer sans labo. ## Comment - **Stockage** (`internal/store`) : SQLite en Go pur (modernc, CGO_ENABLED=0). On y garde les clusters, les paramètres, les utilisateurs, le journal et l'audit. - Les secrets des tokens sont chiffrés en AES-256-GCM. La clé est lue dans `CONFSYNC_SECRET_KEY`, sinon `_FILE`, sinon `DATA_DIR/secret.key`. - Les secrets ne sont jamais renvoyés au navigateur. L'export YAML les remplace par `token_secret_env`. - **Serveur** (`internal/server`) : - Authentification par comptes locaux (PBKDF2-SHA256, 600 000 itérations) et OIDC (code + PKCE, rôle déduit des groupes). - Trois rôles : admin, operator, viewer. - Sessions par cookie signé, invalidé au changement de mot de passe. - Protection CSRF : l'en-tête `X-Confsync` est exigé sur les écritures. La CSP n'autorise aucun script ni style en ligne. - **Synchronisation** : - Chaque dry-run est enregistré avec une empreinte du plan. L'apply recalcule le plan et répond 409 si l'empreinte a changé. - Les changements SDN demandent de taper le nom du client, ou celui de la référence pour une synchro globale. - Un seul apply tourne à la fois, en tâche de fond, et chaque étape est écrite dans le journal. - **Sélection** (`engine.Filter`) : - Sélectionner un objet ajoute ses dépendances : la zone et le vnet parents à créer, ou les enfants à supprimer d'abord. - Une erreur sur un parent reste bloquante quand on ne sélectionne que l'enfant. - **UI** (`web/`) : HTML, CSS et JS sans framework ni build. Elle est en français et en anglais, avec thème clair ou sombre et une mise en page mobile. Les paramètres couvrent les clusters (test d'accès, TLS, mapping et politiques par client), la synchronisation, les utilisateurs, l'import/export YAML, le compte et l'apparence. - **Docker** : `CMD ["serve"]` avec un healthcheck. Le compose a un service `confsync-web` et un service CLI sous le profil `cli`. ## Tests - `go vet` et `go test -race ./...` passent. gofmt est propre et le build passe avec `CGO_ENABLED=0`. - Nouveaux tests : - `engine/select_test.go` : dépendances, ordre des suppressions, erreurs des parents, empreinte. - `store/store_test.go` : chiffrement, masquage des secrets, utilisateurs, dernier admin protégé. - `server/server_test.go` : rôles, CSRF, absence de secret dans les réponses, puis le parcours complet dry-run → refus (bloquant, confirmation, empreinte périmée) → apply → client conforme. - Parcours manuel en Chromium (Playwright) sur le mode démo : aucune erreur JS. ## Limites connues - **Pas testé sur de vrais clusters PVE**, seulement sur le faux serveur. - La synchro globale est bloquée dès qu'un client a une erreur ou est illisible. C'est un choix prudent. - `Auth.CheckProvider` existe mais n'est pas appelé au démarrage dans `serve.go`. - `clientIP` fait confiance à `X-Forwarded-For` (comme Logstream), à restreindre si le service est exposé sans reverse proxy. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_015a8P6WMRPeqdpd5VCh6jAy
claude Bot added 8 commits 2026-10-13 16:13:46 +02:00
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015a8P6WMRPeqdpd5VCh6jAy
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015a8P6WMRPeqdpd5VCh6jAy
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015a8P6WMRPeqdpd5VCh6jAy
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015a8P6WMRPeqdpd5VCh6jAy
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015a8P6WMRPeqdpd5VCh6jAy
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015a8P6WMRPeqdpd5VCh6jAy
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015a8P6WMRPeqdpd5VCh6jAy
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015a8P6WMRPeqdpd5VCh6jAy
claude Bot marked the pull request as ready for review 2026-10-13 16:46:57 +02:00
claude Bot merged commit 5561bcfcf9 into main 2026-10-13 16:47:35 +02:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: vLab-BZH/pve-confsync#1