docs: README complet + RUNBOOK + CHANGELOG + export openapi.json
Build & Deploy / build (push) Successful in 12s
Build & Deploy / build (push) Successful in 12s
This commit is contained in:
@@ -0,0 +1,29 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
Format : [Keep a Changelog](https://keepachangelog.com/fr/) · Versioning sémantique.
|
||||||
|
|
||||||
|
## [1.1.0] — 2026-06-20
|
||||||
|
|
||||||
|
### Ajouté
|
||||||
|
- Authentification **JWT** (`/auth/login`, `/auth/me`) + hachage bcrypt (`auth.py`).
|
||||||
|
- **RBAC** : protection de tous les endpoints de données (401 sans token), routes `/admin/*`
|
||||||
|
réservées au rôle `Admin` (403 sinon).
|
||||||
|
- Endpoints d'administration : CRUD utilisateurs (`/admin/users`), reset de mot de passe,
|
||||||
|
journal d'audit (`/admin/journal`).
|
||||||
|
- **RGPD** : `GET /me/data-export` (portabilité), `DELETE /me` (droit à l'oubli + anonymisation).
|
||||||
|
- En-têtes de sécurité HTTP + rate-limit `5/min` sur le login (`slowapi`).
|
||||||
|
- Connexion DB et CORS configurables par variables d'environnement (auth SQL, Driver 18).
|
||||||
|
- `Dockerfile` + CI Gitea Actions (build → tests pytest → push image) + notifications ntfy.
|
||||||
|
- Tests `pytest` (auth, RBAC, endpoints) avec curseur SQL simulé.
|
||||||
|
- Tables `[USER]` + `JOURNAL_AUDIT` et comptes de démo.
|
||||||
|
|
||||||
|
### Modifié
|
||||||
|
- CORS : tous les verbes + credentials (au lieu de `GET` seul).
|
||||||
|
|
||||||
|
### Sécurité
|
||||||
|
- Plus aucun secret en dur côté déploiement (secrets via env / fichiers hors dépôt).
|
||||||
|
- La base s'exécute sur un SQL Server partagé ; compte applicatif non-`sa`.
|
||||||
|
|
||||||
|
## [1.0.0] — 2026-04
|
||||||
|
- Version initiale (A. Coyaud) : API de lecture sur SQL Server (référentiels, monitorings,
|
||||||
|
dashboard, historique, évolution).
|
||||||
@@ -1,34 +1,85 @@
|
|||||||
# Api-DataSentinel
|
# Api-DataSentinel
|
||||||
|
|
||||||
API FastAPI pour Data Sentinel.
|
API **FastAPI** de monitoring de la qualité des données — Data Sentinel (XEFI).
|
||||||
|
Backend en lecture seule sur SQL Server, sécurisé par authentification JWT.
|
||||||
|
|
||||||
## Installation
|
## Stack
|
||||||
|
|
||||||
1. Ouvrir un terminal dans le dossier du projet :
|
- Python 3.12 · FastAPI 0.136 · uvicorn
|
||||||
```powershell
|
- SQL Server 2022 via `pyodbc` (ODBC Driver 18)
|
||||||
cd "c:\Users\antho\Desktop\Projet de fin d'année\Projet fin d_année\DataSentinel\Api-DataSentinel"
|
- Auth : JWT (`python-jose`) + bcrypt (`passlib`), rate-limit (`slowapi`)
|
||||||
```
|
|
||||||
2. Créer et activer l'environnement virtuel (si nécessaire) :
|
|
||||||
```powershell
|
|
||||||
python -m venv .venv
|
|
||||||
.\.venv\Scripts\Activate.ps1
|
|
||||||
```
|
|
||||||
3. Installer les dépendances :
|
|
||||||
```powershell
|
|
||||||
pip install -r requirements.txt
|
|
||||||
```
|
|
||||||
|
|
||||||
## Lancement de l'API
|
## Lancement en local (dev)
|
||||||
|
|
||||||
Utiliser la commande suivante pour démarrer le serveur :
|
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
.\.venv\Scripts\python.exe -m uvicorn main:app --reload --port 8000
|
python -m venv .venv
|
||||||
|
.\.venv\Scripts\Activate.ps1
|
||||||
|
pip install -r requirements.txt
|
||||||
|
python -m uvicorn main:app --reload --port 8000
|
||||||
```
|
```
|
||||||
|
|
||||||
> Important : si le lanceur `\.venv\Scripts\uvicorn.exe` est cassé après un déplacement de dossier, utilisez toujours `python -m uvicorn`.
|
- Swagger : `http://127.0.0.1:8000/docs` · Santé : `http://127.0.0.1:8000/health`
|
||||||
|
|
||||||
## Vérification
|
Sans variables d'environnement, l'API se connecte en authentification Windows
|
||||||
|
(`LaptopCA\SQLEXPRESS`) — comportement de dev d'origine, inchangé.
|
||||||
|
|
||||||
- Swagger : `http://127.0.0.1:8000/docs`
|
## Configuration (variables d'environnement)
|
||||||
- Santé : `http://127.0.0.1:8000/health`
|
|
||||||
|
| Variable | Rôle | Défaut |
|
||||||
|
|----------|------|--------|
|
||||||
|
| `DB_SERVER` | hôte SQL Server (active l'auth SQL si défini) | — (sinon Windows local) |
|
||||||
|
| `DB_PORT` / `DB_NAME` | port / base | `1433` / `DataSentinel` |
|
||||||
|
| `DB_USER` / `DB_PASSWORD` | compte applicatif | — |
|
||||||
|
| `DB_DRIVER` | pilote ODBC | `ODBC Driver 18 for SQL Server` |
|
||||||
|
| `CORS_ORIGINS` | origines autorisées (séparées par `,`) | `localhost:5173,localhost:3000` |
|
||||||
|
| `JWT_SECRET` | clé de signature JWT | placeholder (à définir en prod) |
|
||||||
|
| `JWT_ALGORITHM` / `JWT_EXPIRE_MINUTES` | algo / durée du token | `HS256` / `60` |
|
||||||
|
|
||||||
|
## Authentification & rôles
|
||||||
|
|
||||||
|
- `POST /auth/login` (form `username`/`password`) → `{access_token, token_type, user}`. Rate-limité **5/min**.
|
||||||
|
- `GET /auth/me` → profil courant.
|
||||||
|
- **Tous les endpoints de données exigent** `Authorization: Bearer <token>` (401 sinon). Seul `/health` est public.
|
||||||
|
- Rôles : `Admin`, `Superviseur`, `Consultant`. Les routes `/admin/*` exigent `Admin` (403 sinon).
|
||||||
|
|
||||||
|
### Comptes de démo
|
||||||
|
|
||||||
|
| Identifiant | Mot de passe | Rôle |
|
||||||
|
|-------------|--------------|------|
|
||||||
|
| `admin` | `Admin2026!` | Admin |
|
||||||
|
| `superviseur` | `Super2026!` | Superviseur |
|
||||||
|
| `consultant` | `Conseil2026!` | Consultant |
|
||||||
|
|
||||||
|
## Endpoints (résumé)
|
||||||
|
|
||||||
|
- **Données** (protégés) : `/categories`, `/services`, `/contacts`, `/monitorings[...]`,
|
||||||
|
`/dashboard[...]`, `/historique[...]`, `/evolution/*`.
|
||||||
|
- **Admin** (`Admin`) : `GET/POST /admin/users`, `PUT/DELETE /admin/users/{id}`,
|
||||||
|
`POST /admin/users/{id}/reset-password`, `GET /admin/journal`.
|
||||||
|
- **RGPD** : `GET /me/data-export` (portabilité), `DELETE /me` (droit à l'oubli + anonymisation).
|
||||||
|
|
||||||
|
Spécification complète : `GET /openapi.json` (export dans `docs/openapi.json`).
|
||||||
|
|
||||||
|
## Sécurité
|
||||||
|
|
||||||
|
- En-têtes : `X-Content-Type-Options`, `X-Frame-Options`, `Referrer-Policy`, `Strict-Transport-Security`.
|
||||||
|
- CORS restreint aux origines `CORS_ORIGINS`, tous verbes + credentials.
|
||||||
|
- Requêtes SQL **paramétrées** (noms de tables/colonnes whitelistés) ; le compte applicatif
|
||||||
|
n'est pas `sa`. Tables d'auth : `[USER]` + `JOURNAL_AUDIT` (`sql/data_sentinel_auth.sql`).
|
||||||
|
- Journal d'audit alimenté à chaque login + action admin.
|
||||||
|
|
||||||
|
## Tests
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pip install pytest httpx && pytest -q
|
||||||
|
```
|
||||||
|
Curseur SQL simulé (aucune vraie BDD) : santé, auth (succès/échec), protection 401, RBAC 403, 404.
|
||||||
|
|
||||||
|
## Docker & CI/CD
|
||||||
|
|
||||||
|
- `Dockerfile` : image Python 3.12 + `msodbcsql18`.
|
||||||
|
- CI Gitea Actions (`.gitea/workflows/build.yml`) : **build → pytest (dans l'image) → push**
|
||||||
|
vers `git.nfteam.ovh/neckfire/datasentinel-api` + notification ntfy. Déclenché sur push `main`.
|
||||||
|
- Déploiement, exploitation, sauvegarde : voir `RUNBOOK.md` et le stack d'hébergement
|
||||||
|
(`homelab/dev/datasentinel/`). La base tourne sur un **SQL Server partagé** (`dev-mssql`),
|
||||||
|
pas dédiée à l'app.
|
||||||
|
|||||||
+80
@@ -0,0 +1,80 @@
|
|||||||
|
# RUNBOOK — Data Sentinel (déploiement & exploitation)
|
||||||
|
|
||||||
|
Hébergement sur le homelab `nfteam.ovh`. Stack d'exécution :
|
||||||
|
`~/Documents/homelab/dev/datasentinel/` (API + Front) et `~/Documents/homelab/dev/mssql/`
|
||||||
|
(SQL Server partagé `dev-mssql`, réseau externe `dev-shared`).
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
| Composant | URL publique | Port interne | Conteneur |
|
||||||
|
|-----------|--------------|--------------|-----------|
|
||||||
|
| Front (React) | https://datasentinel.nfteam.ovh | 8086 | `datasentinel-front` |
|
||||||
|
| API (FastAPI) | https://datasentinel-api.nfteam.ovh | 8001 | `datasentinel-api` |
|
||||||
|
| Base | — (réseau `dev-shared`) | 1433 | `dev-mssql` (partagé) |
|
||||||
|
|
||||||
|
Reverse proxy : Nginx Proxy Manager (HTTPS Let's Encrypt). CI : Gitea Actions →
|
||||||
|
images poussées au registre `git.nfteam.ovh`, déployées par `docker compose` / Watchtower.
|
||||||
|
|
||||||
|
## Déploiement / mise à jour
|
||||||
|
|
||||||
|
Un push sur `main` (API ou Front) déclenche la CI (build → tests → push image).
|
||||||
|
Récupérer la dernière image et redéployer :
|
||||||
|
```bash
|
||||||
|
cd ~/Documents/homelab/dev/datasentinel
|
||||||
|
docker compose pull && docker compose up -d
|
||||||
|
```
|
||||||
|
Watchtower met aussi à jour automatiquement (~5 min).
|
||||||
|
|
||||||
|
## Diagnostic incidents
|
||||||
|
|
||||||
|
| Symptôme | Diagnostic | Résolution |
|
||||||
|
|----------|-----------|------------|
|
||||||
|
| Front KO | `curl -I https://datasentinel.nfteam.ovh` ; `docker logs datasentinel-front` | `docker compose restart datasentinel-front` |
|
||||||
|
| API 5xx | `curl https://datasentinel-api.nfteam.ovh/health` → champ `database` | si `error` → voir BDD ci-dessous ; `docker logs datasentinel-api` |
|
||||||
|
| BDD injoignable | `docker ps | grep dev-mssql` ; tester la connexion (cf. ci-dessous) | `docker compose -f ~/Documents/homelab/dev/mssql/docker-compose.yml up -d` |
|
||||||
|
| Token invalide / 401 partout | vérifier `JWT_SECRET` dans `api.env` (ne pas le changer à chaud : invalide les sessions) | re-login |
|
||||||
|
| Login 429 | rate-limit 5/min atteint | attendre 1 min |
|
||||||
|
|
||||||
|
Connexion BDD (admin) :
|
||||||
|
```bash
|
||||||
|
SA=$(grep ^SA_PASSWORD= ~/Documents/homelab/dev/mssql/.env | cut -d= -f2-)
|
||||||
|
docker run --rm --network dev-shared mcr.microsoft.com/mssql-tools \
|
||||||
|
/opt/mssql-tools/bin/sqlcmd -S dev-mssql -U sa -P "$SA" -d DataSentinel -Q "SELECT COUNT(*) FROM [USER];"
|
||||||
|
```
|
||||||
|
|
||||||
|
## (Re)chargement du schéma
|
||||||
|
|
||||||
|
```bash
|
||||||
|
SA=$(grep ^SA_PASSWORD= ~/Documents/homelab/dev/mssql/.env | cut -d= -f2-)
|
||||||
|
for f in data_sentinel_init.sql data_sentinel_auth.sql; do
|
||||||
|
docker run --rm --network dev-shared \
|
||||||
|
-v ~/Documents/homelab/dev/datasentinel/sql:/sql:ro mcr.microsoft.com/mssql-tools \
|
||||||
|
/opt/mssql-tools/bin/sqlcmd -S dev-mssql -U sa -P "$SA" -i /sql/$f
|
||||||
|
done
|
||||||
|
```
|
||||||
|
|
||||||
|
## Sauvegarde / restauration
|
||||||
|
|
||||||
|
> ⚠️ Stratégie à finaliser avec le disque de sauvegarde dédié du homelab.
|
||||||
|
|
||||||
|
Sauvegarde logique recommandée (quotidienne) :
|
||||||
|
```bash
|
||||||
|
SA=$(grep ^SA_PASSWORD= ~/Documents/homelab/dev/mssql/.env | cut -d= -f2-)
|
||||||
|
docker exec dev-mssql /opt/mssql-tools*/bin/sqlcmd -S localhost -U sa -P "$SA" \
|
||||||
|
-Q "BACKUP DATABASE DataSentinel TO DISK='/var/opt/mssql/backup/DataSentinel.bak' WITH FORMAT, INIT, COMPRESSION"
|
||||||
|
```
|
||||||
|
(monter un volume `/var/opt/mssql/backup` vers le disque de sauvegarde). Le volume
|
||||||
|
Docker `mssql_data` contient les fichiers de la base. RTO visé < 4h, RPO < 24h.
|
||||||
|
|
||||||
|
## Rollback
|
||||||
|
|
||||||
|
Redéployer une image précise par son tag SHA (au lieu de `latest`) :
|
||||||
|
```bash
|
||||||
|
# dans dev/datasentinel/docker-compose.yml : image: .../datasentinel-api:<sha>
|
||||||
|
docker compose up -d datasentinel-api
|
||||||
|
```
|
||||||
|
|
||||||
|
## Contacts
|
||||||
|
|
||||||
|
- Hébergement / infra : administrateur homelab (neckfire).
|
||||||
|
- Application / code : A. Coyaud (auteur, dépôts GitHub).
|
||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user