259 lines
10 KiB
Markdown
259 lines
10 KiB
Markdown
# 🔒 Guide Authentification & sécurité
|
|
|
|
ObsiGate embarque un système d'authentification optionnel **JWT + Argon2id**,
|
|
un contrôle d'accès **par vault**, du MFA (TOTP, WebAuthn, codes de secours) et
|
|
des mécanismes de durcissement. Ce guide couvre l'activation, la gestion des
|
|
comptes et les bonnes pratiques.
|
|
|
|
> **Public :** administrateurs · **Voir aussi :**
|
|
> [`features/api-mcp-tokens-107.md`](../features/api-mcp-tokens-107.md) ·
|
|
> [API REST](./API_REST.md) · [MCP](./MCP.md) · [Déploiement Docker](./DEPLOIEMENT_DOCKER.md)
|
|
|
|
---
|
|
|
|
## 1. Vue d'ensemble
|
|
|
|
- **Désactivée par défaut** (`OBSIGATE_AUTH_ENABLED=false`) — compatible avec
|
|
toutes les installations existantes.
|
|
- Quand elle est activée, l'écran de connexion s'affiche et chaque endpoint
|
|
vérifie l'utilisateur et ses permissions.
|
|
- Les données d'auth (`users.json`, `secret.key`, `api_tokens.json`) vivent dans
|
|
`/app/data` — **montez ce dossier en volume** pour les persister.
|
|
|
|
---
|
|
|
|
## 2. Activer l'authentification
|
|
|
|
### 2.1 Fichier `.env`
|
|
|
|
```bash
|
|
cp .env.example .env
|
|
```
|
|
|
|
```bash
|
|
OBSIGATE_AUTH_ENABLED=true
|
|
OBSIGATE_ADMIN_USER=admin
|
|
OBSIGATE_ADMIN_PASSWORD=votre_mot_de_passe # vide = auto-généré (voir logs)
|
|
# OBSIGATE_SECURE_COOKIES=false # true si derrière HTTPS
|
|
```
|
|
|
|
### 2.2 `docker-compose.yml`
|
|
|
|
```yaml
|
|
env_file:
|
|
- .env
|
|
```
|
|
|
|
> **Ne mettez jamais de mot de passe dans `docker-compose.yml` !** Utilisez
|
|
> toujours `.env` (non committé).
|
|
|
|
### 2.3 Premier démarrage
|
|
|
|
Si aucun utilisateur n'existe, ObsiGate crée un compte admin et affiche le mot de
|
|
passe **une seule fois dans les logs** :
|
|
|
|
```bash
|
|
docker compose logs obsigate | grep -A4 "FIRST"
|
|
```
|
|
|
|
```
|
|
============================================================
|
|
FIRST STARTUP — Admin account created automatically
|
|
Username : admin
|
|
Password : xK9mQ3pLr7wN2jT5
|
|
CHANGE THIS PASSWORD on first login!
|
|
============================================================
|
|
```
|
|
|
|
Changez-le immédiatement (menu profil → *Changer le mot de passe*).
|
|
|
|
Vous pouvez aussi ajouter une **photo de profil** : *Configurations → Profil →
|
|
Choisir une image* (PNG, JPG ou WEBP, 8 Mo maximum — recadrée en carré 256 px).
|
|
Elle remplace les initiales dans le cercle du compte en bas de la sidebar et peut
|
|
être supprimée à tout moment depuis la même section.
|
|
|
|
---
|
|
|
|
## 3. Gestion des utilisateurs
|
|
|
|
### 3.1 Interface d'administration
|
|
|
|
Un compte **admin** voit une icône 🛡️ dans le header. Le panneau permet de :
|
|
|
|
- lister tous les utilisateurs ;
|
|
- créer / modifier / supprimer des comptes ;
|
|
- assigner les vaults accessibles par utilisateur ;
|
|
- activer / désactiver des comptes.
|
|
|
|
### 3.2 Ligne de commande
|
|
|
|
```bash
|
|
# Créer un utilisateur
|
|
docker exec obsigate python backend/create_admin.py create alice MotDePasse --role user --vaults Recettes IT
|
|
|
|
# Créer un admin avec accès total
|
|
docker exec obsigate python backend/create_admin.py create bob SecretPass --role admin --vaults "*"
|
|
|
|
# Lister
|
|
docker exec obsigate python backend/create_admin.py list
|
|
|
|
# Supprimer
|
|
docker exec obsigate python backend/create_admin.py delete alice
|
|
```
|
|
|
|
### 3.3 Contrôle d'accès par vault
|
|
|
|
| Valeur `vaults` | Accès |
|
|
|---|---|
|
|
| `["*"]` | Toutes les vaults (y compris futures) — défaut admin |
|
|
| `["Recettes", "IT"]` | Uniquement ces vaults |
|
|
| `[]` | Aucun accès |
|
|
|
|
Les permissions sont revérifiées à chaque requête (et à chaque connexion
|
|
WebSocket de collaboration).
|
|
|
|
---
|
|
|
|
## 4. MFA (authentification multifacteur)
|
|
|
|
ObsiGate propose trois secondes facteurs, configurables par l'utilisateur.
|
|
|
|
### 4.1 TOTP (application d'authentification)
|
|
|
|
1. Menu profil → **Sécurité** → *Configurer TOTP* (`POST /api/auth/mfa/totp/setup`).
|
|
2. Scannez le QR code avec Google Authenticator, Authy, etc.
|
|
3. Validez le code (`POST /api/auth/mfa/totp/enable`).
|
|
4. Désactivation : `POST /api/auth/mfa/totp/disable` (mot de passe requis).
|
|
|
|
### 4.2 Clés de sécurité & biométrie (WebAuthn)
|
|
|
|
- Enregistrement : `POST /api/auth/mfa/webauthn/register/options` puis
|
|
`POST /api/auth/mfa/webauthn/register`.
|
|
- Connexion : `POST /api/auth/mfa/webauthn/options` puis `/verify`.
|
|
- Gestion des clés : `GET /api/auth/mfa/webauthn/credentials`,
|
|
`POST /api/auth/mfa/webauthn/credentials/remove`.
|
|
|
|
> Le *relying party* (domaine) est **dérivé de la requête** (hôte exact, port
|
|
> inclus) ; derrière un reverse proxy, activez `OBSIGATE_TRUST_PROXY=true` pour
|
|
> que `X-Forwarded-Host/Proto` soient pris en compte.
|
|
|
|
### 4.3 Codes de secours
|
|
|
|
À l'activation du MFA, des **codes de récupération** sont générés. Utilisez-en un
|
|
via `POST /api/auth/mfa/recovery` si vous perdez votre second facteur. Conservez-
|
|
les hors ligne.
|
|
|
|
### 4.4 Statut
|
|
|
|
`GET /api/auth/mfa/status` indique les facteurs actifs pour le compte courant.
|
|
|
|
---
|
|
|
|
## 5. Clés API & MCP
|
|
|
|
Pour les scripts et les clients externes, créez une **clé API longue durée**
|
|
(1 j, 1 mois, 6 mois, 1 an, sans fin) depuis Configurations → 🔑 **Clés API &
|
|
MCP**. Une seule clé authentifie l'API REST **et** le serveur MCP.
|
|
|
|
- Le secret n'est **affiché qu'une fois** (pattern GitHub) et n'est jamais persisté.
|
|
- La révocation est **immédiate** des deux côtés.
|
|
- Une colonne « dernière utilisation » (throttlée) aide à repérer les clés
|
|
dormantes.
|
|
|
|
Détails : [API REST §2.2](./API_REST.md#22-clés-api-longue-durée-recommandé-pour-scripts--mcp)
|
|
et [`features/api-mcp-tokens-107.md`](../features/api-mcp-tokens-107.md).
|
|
|
|
---
|
|
|
|
## 6. Mécanismes de durcissement
|
|
|
|
| Mécanisme | Détail |
|
|
|---|---|
|
|
| **Path traversal** | Chaque endpoint fichier valide que le chemin résolu reste dans la vault |
|
|
| **Rate limiting** | 10 tentatives de login max par IP / 15 min + lockout par compte |
|
|
| **Rate limiting MFA** | Appliqué aux endpoints TOTP/WebAuthn/recovery |
|
|
| **Audit log** | Écritures, suppressions, config dans `data/audit.log` (JSON lines, rotation 10 Mo) |
|
|
| **Backup automatique** | Avant chaque modification/suppression dans `.obsigate-backup/` |
|
|
| **Redaction** | Masquage des JWT, mots de passe, clés API (OpenAI, GitHub, Google, AWS, Slack, Stripe…), tokens et connection strings dans les aperçus markdown et les retours d'outils — clic sur un masque = copie de la valeur |
|
|
| **CSP** | `object-src`, `base-uri`, `form-action`, `frame-ancestors` restreints |
|
|
| **Cookie HttpOnly** | Jeton retiré de `sessionStorage`, porté par cookie HTTP-only |
|
|
| **Utilisateur non-root** | Conteneur sous `obsigate` (UID 1000) |
|
|
| **Volumes read-only** | Vaults montées `:ro` par défaut |
|
|
| **Atomic writes** | `users.json`, `shares.json`, `webhooks.json` écrits en tmp+replace |
|
|
| **Symlinks ignorés** | L'index n'indexe pas les liens symboliques |
|
|
|
|
### Politique de mot de passe
|
|
|
|
Une politique minimale est validée à la création d'un compte. Choisissez des mots
|
|
de passe longs et uniques ; activez le MFA pour les comptes admin.
|
|
|
|
### Secrets masqués dans les aperçus
|
|
|
|
Quand une note contient un secret, l'aperçu markdown le remplace par un masque
|
|
— `[CLÉ API MASQUÉE]`, `[MOT DE PASSE MASQUÉ]`, `[JWT MASQUÉ]`,
|
|
`[CONNECTION_STRING MASQUÉE]` — au lieu de la valeur :
|
|
|
|
- **Détectés automatiquement** : mots de passe (`password=`, `"passwd": "…"`,
|
|
`db_password=…`, toute longueur), affectations `api_key=` / `token=` /
|
|
`secret=`, JWT, clés privées, connection strings, hex en contexte secret,
|
|
et les formats de clés les plus répandus — OpenAI/Anthropic/OpenRouter
|
|
(`sk-`), GitHub (`ghp_`, `github_pat_`), Google (`AIza…`, `ya29.`), AWS
|
|
(`AKIA…`/`ASIA…`), Slack (`xoxb-`), Stripe (`sk_live_`, `whsec_`), GitLab
|
|
(`glpat-`), Hugging Face (`hf_`), npm, Docker, SendGrid, Resend, Square,
|
|
Atlassian, Discord, Telegram, jetons `Bearer …`.
|
|
- **Clic = copie** : dans l'application (aperçu authentifié), cliquer sur un
|
|
masque copie la valeur réelle dans le presse-papiers (infobulle « Cliquer
|
|
pour copier la valeur »). La valeur n'apparaît jamais en clair à l'écran.
|
|
- **Jamais exposé à l'extérieur** : partages publics (`/s/{token}`), exports
|
|
PDF et contexte envoyé à l'IA / au serveur MCP ne reçoivent que le libellé,
|
|
jamais la valeur derrière le masque.
|
|
- **Hors périmètre** : la vue « source » (fichier brut) et les aperçus de
|
|
fichiers non-markdown ne sont pas masqués — c'est le fichier lui-même qui
|
|
est affiché.
|
|
|
|
---
|
|
|
|
## 7. Variables d'environnement
|
|
|
|
| Variable | Description | Défaut |
|
|
|---|---|---|
|
|
| `OBSIGATE_AUTH_ENABLED` | Activer l'authentification | `false` |
|
|
| `OBSIGATE_ADMIN_USER` | Nom de l'admin auto-créé | `admin` |
|
|
| `OBSIGATE_ADMIN_PASSWORD` | Mot de passe admin (vide = auto-généré) | *(auto)* |
|
|
| `OBSIGATE_SECURE_COOKIES` | Cookie `Secure` (HTTPS uniquement) | `false` |
|
|
| `OBSIGATE_ACCESS_TOKEN_TTL` | Durée de vie du token d'accès (s) | `3600` |
|
|
| `OBSIGATE_REFRESH_TOKEN_TTL` | Durée de vie du refresh token (s) | `2592000` |
|
|
| `OBSIGATE_LOGIN_MAX_ATTEMPTS` | Tentatives de login max par IP | `10` |
|
|
| `OBSIGATE_ACCOUNT_MAX_ATTEMPTS` | Tentatives de login max par compte | `10` |
|
|
| `OBSIGATE_LOGIN_WINDOW_SECONDS` | Fenêtre de rate limiting (s) | `900` |
|
|
| `OBSIGATE_TRUST_PROXY` | Faire confiance à `X-Forwarded-For` / `Host` | `false` |
|
|
|
|
Toutes ces variables sont documentées dans `.env.example`.
|
|
|
|
---
|
|
|
|
## 8. Déploiement sécurisé (checklist)
|
|
|
|
- [ ] `OBSIGATE_AUTH_ENABLED=true` sur toute instance exposée.
|
|
- [ ] Mot de passe admin fort, changé après le premier démarrage.
|
|
- [ ] MFA activé pour les comptes admin.
|
|
- [ ] HTTPS via reverse proxy + `OBSIGATE_SECURE_COOKIES=true`.
|
|
- [ ] `OBSIGATE_TRUST_PROXY=true` **uniquement** derrière un proxy de confiance.
|
|
- [ ] Volume `./data:/app/data` monté et **sauvegardé**.
|
|
- [ ] Vaults montées en `:ro` (lecture seule) sauf besoin d'écriture.
|
|
- [ ] Clés API révoquées dès qu'elles ne servent plus.
|
|
- [ ] Accès réseau restreint (VPN / pare-feu) si possible.
|
|
|
|
---
|
|
|
|
## 9. Dépannage
|
|
|
|
| Symptôme | Piste |
|
|
|---|---|
|
|
| Login bloqué `429` | Rate limit : attendre la fenêtre (`OBSIGATE_LOGIN_WINDOW_SECONDS`) |
|
|
| WebAuthn refuse l'enregistrement | Domaine/port non dérivés — activer `OBSIGATE_TRUST_PROXY` derrière un proxy |
|
|
| TOTP « challenge inattendu » | Relancer la cérémonie ; les 5 derniers challenges sont acceptés |
|
|
| Perte du second facteur | Utiliser un code de secours (`/api/auth/mfa/recovery`) |
|
|
| Sessions perdues au redémarrage | Le volume `./data` n'est pas monté |
|
|
| Clé API `401` | Clé expirée ou révoquée — en créer une nouvelle |
|