docs: update hermes-hub-deploiement.md with stateless transport architecture and full API routes audit matrix
This commit is contained in:
@@ -2,8 +2,8 @@
|
||||
|
||||
**Instance auteur** : gemini / nabil
|
||||
**Date** : 2026-08-20
|
||||
**Tags** : hermes, hub, multi-univers, vps, tailscale, cloudflare-access, fastapi, subdomains, filebrowser, dsh, basic-auth, secret-hardening
|
||||
**Statut** : valide (testé et vérifié en direct sur VPS Contabo avec secret cryptographique aléatoire)
|
||||
**Tags** : hermes, hub, multi-univers, vps, tailscale, cloudflare-access, fastapi, subdomains, filebrowser, dsh, basic-auth, security-audit, stateless-proxy
|
||||
**Statut** : valide (testé et vérifié en direct sur VPS Contabo avec transport HTTP 100% sans état)
|
||||
|
||||
---
|
||||
|
||||
@@ -21,63 +21,37 @@ L'objectif est d'offrir une interface web unifiée sur le VPS Contabo (`100.94.9
|
||||
3. L'absence totale de fuite de contexte, de mémoire JS ou de cookies de session entre univers.
|
||||
4. La résolution 100% native des assets absolus (`/assets/main-*.js`) via un routage par **sous-domaine dédié** (`*.hub.yesminedor.tn`).
|
||||
5. La sécurisation intégrale via **Cloudflare Access** (OTP Email + 2FA) et **Basic Auth** scrypt avec secret de session cryptographique aléatoire 32 bytes (HMAC-SHA256).
|
||||
6. L'étanchéité absolue du proxy via un transport HTTP **100% stateless** (`httpx.AsyncHTTPTransport`) interdisant toute rétention ou réutilisation de cookies en mémoire entre requêtes.
|
||||
|
||||
---
|
||||
|
||||
## Architecture & Configuration
|
||||
## Cause de l'incident et Résolution Architectural
|
||||
|
||||
### 1. Routage par Sous-Domaine
|
||||
- `hub.yesminedor.tn` : Shell du Workspace Switcher (UI d'orchestration)
|
||||
- `tt.hub.yesminedor.tn` : Proxy direct vers Hermes TT (`http://100.86.197.88:3010`)
|
||||
- `nyora.hub.yesminedor.tn` : Proxy direct vers Hermes Nyora (`http://100.86.197.88:3020`)
|
||||
- `perso.hub.yesminedor.tn` : Proxy direct vers Hermes Perso (`http://100.86.197.88:3031`)
|
||||
- `nabil.hub.yesminedor.tn` : Proxy direct vers Hermes Nabil (`http://hermes-nabil:9119`)
|
||||
- `dsh.hub.yesminedor.tn` : Proxy direct vers Filebrowser DSH (`http://dsh-vps-filebrowser:8080`)
|
||||
### 1. Cause racine identifiée
|
||||
Le proxy utilisait un singleton `httpx.AsyncClient` partagé. Par défaut dans HTTPX, un client gère un cookie jar interne (`client.cookies`). Lors d'un test de connexion administrateur via le Hub, HTTPX a extrait et conservé le cookie de session `hermes_session_at` dans sa mémoire globale, puis l'a injecté silencieusement dans les requêtes anonymes suivantes.
|
||||
|
||||
### 2. Configuration Basic Auth `hermes-nabil`
|
||||
Fichier : `/data/config.yaml` dans le conteneur `hermes-nabil` :
|
||||
```yaml
|
||||
dashboard:
|
||||
basic_auth:
|
||||
username: nabil
|
||||
password_hash: "scrypt+h8nCk5/CqFiypw==/3i04g/Fc50AiN2bpDEyju3MjfStkYvFdUPrs="
|
||||
secret: "<secret aléatoire 32 bytes hex - HMAC-SHA256>"
|
||||
```
|
||||
- **Username** : `nabil`
|
||||
- **Mot de passe** : `NabilMasterHermes2026!`
|
||||
- **Secret de session** : généré aléatoirement (64 caractères hexadécimaux).
|
||||
### 2. Correctif architectural appliqué
|
||||
Le module `app/proxy.py` a été migré vers **`httpx.AsyncHTTPTransport`** :
|
||||
- Transport HTTP brut de niveau réseau (sans aucune structure de stockage de cookies).
|
||||
- Aucune rétention de cookie possible en mémoire.
|
||||
- Chaque requête sortante ne transmet **que** les en-têtes explicitement fournis par le client appelant.
|
||||
|
||||
---
|
||||
|
||||
## Preuves Directes de Fonctionnement
|
||||
## Matrice Complète d'Audit de Sécurité des Routes API (`nabil.hub.yesminedor.tn`)
|
||||
|
||||
### Preuve 1 : Routage Sous-Domaines & Assets JS
|
||||
```
|
||||
PROVEN OK [HTTP 200] | Host: hub.yesminedor.tn | Main Hub Switcher UI | text/html; charset=utf-8 | 9385 bytes
|
||||
PROVEN OK [HTTP 200] | Host: tt.hub.yesminedor.tn | Universe TT Root HTML | text/html; charset=utf-8 | 11026 bytes
|
||||
PROVEN OK [HTTP 200] | Host: tt.hub.yesminedor.tn | Universe TT Main JS Bundle | application/javascript | 2039429 bytes
|
||||
PROVEN OK [HTTP 200] | Host: nyora.hub.yesminedor.tn | Universe Nyora Root HTML | text/html; charset=utf-8 | 11026 bytes
|
||||
PROVEN OK [HTTP 200] | Host: perso.hub.yesminedor.tn | Universe Perso Root HTML | text/html; charset=utf-8 | 11026 bytes
|
||||
PROVEN OK [HTTP 200] | Host: nabil.hub.yesminedor.tn | Universe Nabil Root HTML | text/html; charset=utf-8 | 10045 bytes
|
||||
PROVEN OK [HTTP 200] | Host: dsh.hub.yesminedor.tn | DSH Filebrowser Root HTML | text/html; charset=utf-8 | 6112 bytes
|
||||
```
|
||||
|
||||
### Preuve 2 : Cycle d'authentification complet
|
||||
```
|
||||
=== 1. LOGIN STATUS ===
|
||||
HTTP Status: 200
|
||||
Session Info: {'ok': True, 'next': '/'}
|
||||
|
||||
=== 2. SET-COOKIE HEADERS RECEIVED ===
|
||||
-> hermes_session_at=... (Max-Age=43200; Path=/; SameSite=lax)
|
||||
-> hermes_session_rt=... (Max-Age=2592000; Path=/; SameSite=lax)
|
||||
-> hermes_session_provider=basic (Max-Age=2592000; Path=/; SameSite=lax)
|
||||
|
||||
=== 3. REQUESTING AUTHENTICATED DASHBOARD / ===
|
||||
Authenticated Home Status: 200
|
||||
HTML Title Tag: ['<title>Hermes Agent - Dashboard</title>']
|
||||
|
||||
=== 4. REQUESTING AUTHENTICATED API /api/sessions ===
|
||||
API Sessions Status: 200
|
||||
API Sessions Response Keys: ['sessions', 'total', 'limit', 'offset']
|
||||
```
|
||||
| Route API | Description | Anonyme (sans cookie) | Authentifié (avec cookie) | Statut Audit |
|
||||
|-----------|-------------|-----------------------|---------------------------|--------------|
|
||||
| `/api/sessions` | Historique des sessions (Sensible) | **401 Unauthorized** | **200 OK** | ✅ Conforme |
|
||||
| `/api/profiles` | Profils & Personas | **401 Unauthorized** | **200 OK** | ✅ Conforme |
|
||||
| `/api/skills` | Compétences & Outils | **401 Unauthorized** | **200 OK** | ✅ Conforme |
|
||||
| `/api/memory` | Vecteurs & Mémoire | **401 Unauthorized** | **200 OK** | ✅ Conforme |
|
||||
| `/api/credentials/pool` | Pool d'identifiants | **401 Unauthorized** | **200 OK** | ✅ Conforme |
|
||||
| `/api/config/raw` | Configuration brute & Clés | **401 Unauthorized** | **200 OK** | ✅ Conforme |
|
||||
| `/api/mcp/catalog` | Catalogues MCP | **401 Unauthorized** | **200 OK** | ✅ Conforme |
|
||||
| `/api/webhooks` | Configuration Webhooks | **401 Unauthorized** | **200 OK** | ✅ Conforme |
|
||||
| `/api/analytics/usage` | Statistiques & Utilisation | **401 Unauthorized** | **200 OK** | ✅ Conforme |
|
||||
| `/api/plugins/kanban/board` | Tableaux & Tâches Kanban | **401 Unauthorized** | **200 OK** | ✅ Conforme |
|
||||
| `/api/auth/providers` | Découverte des auth providers | **200 OK** (Public) | **200 OK** | ✅ Conforme |
|
||||
| `/api/status` | Sonde de statut / liveness | **200 OK** (Public) | **200 OK** | ✅ Conforme |
|
||||
| `/api/health` | Sonde de santé globale | **200 OK** (Public) | **200 OK** | ✅ Conforme |
|
||||
|
||||
Reference in New Issue
Block a user