14 KiB
14 KiB
📐 Architecture Secure Proxy
Vue d'Ensemble
┌─────────────────────────────────────────────────────────────────┐
│ Internet / External Users │
└────────────────────────────┬────────────────────────────────────┘
│ https://secure.k2r.ovh
│
┌────────▼────────┐
│ Nginx/SSL │
│ (Reverse Proxy)│
└────────┬────────┘
│ http://localhost:3000
┌────────────────────▼──────────────────────┐
│ Secure Proxy (Node.js) │
│ ┌──────────────────────────────────────┐ │
│ │ Express Server │ │
│ │ - OIDC Authentication (Keycloak) │ │
│ │ - Session Management │ │
│ │ - Rate Limiting & Security │ │
│ └──────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────┐ │
│ │ Routes │ │
│ │ - /auth/* (Authentification) │ │
│ │ - /api/* (Admin API) │ │
│ │ - /admin (Panel Admin) │ │
│ │ - /* (Reverse Proxy) │ │
│ └──────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────┐ │
│ │ Middleware │ │
│ │ - OIDC Middleware │ │
│ │ - Proxy Middleware │ │
│ │ - Security Middleware │ │
│ └──────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────┐ │
│ │ Database (SQLite) │ │
│ │ - Services Management │ │
│ │ - Audit Logs │ │
│ │ - Access Logs │ │
│ └──────────────────────────────────────┘ │
└──────────────┬──────────────┬──────────────┘
│ │
┌──────────────▼──┐ ┌───────▼──────────────┐
│ Keycloak OIDC │ │ Internal Services │
│ (Authentication)│ │ - API Server │
│ │ │ - Grafana │
└─────────────────┘ │ - React App │
│ - Custom Services │
└─────────────────────┘
Structure des Fichiers
openidv2/
│
├── 📁 src/ # Code source principal
│ ├── server.js # Serveur Express principal
│ ├── config.js # Configuration centralisée
│ ├── db.js # Gestion SQLite
│ │
│ ├── 📁 middleware/
│ │ ├── oidcMiddleware.js # Authentification OIDC/Keycloak
│ │ ├── security.js # Rate limit, CSRF, headers, logs
│ │ └── proxyMiddleware.js # Logique du reverse proxy
│ │
│ ├── 📁 routes/
│ │ ├── authRoutes.js # Routes d'authentification
│ │ ├── adminRoutes.js # API admin (CRUD services)
│ │ └── dashboardRoutes.js # Routes dashboard
│ │
│ ├── 📁 controllers/
│ │ ├── authController.js # Logique auth (login, callback)
│ │ ├── serviceController.js # CRUD des services
│ │ └── adminController.js # Stats et logs
│ │
│ ├── 📁 services/
│ │ └── serviceManager.js # Business logic (DB interactions)
│ │
│ └── 📁 utils/
│ └── logger.js # Logging centralisé
│
├── 📁 public/
│ └── admin.html # Interface admin (UI complète)
│
├── 📁 db/
│ └── services.db # Base de données SQLite
│
├── 📁 scripts/
│ ├── initDb.js # Initialiser la DB
│ └── seedDb.js # Charger données d'exemple
│
├── 📁 sessions/ # Sessions utilisateur (créé à runtime)
│
├── Configuration
│ ├── .env # Variables d'environnement
│ ├── .env.example # Modèle de configuration
│ ├── package.json # Dépendances Node.js
│ ├── docker-compose.yml # Stack Docker (dev)
│ ├── Dockerfile # Image Docker
│ └── nginx.example.conf # Config Nginx
│
└── Documentation
├── README.md # Documentation complète
├── INSTALLATION.md # Guide installation détaillé
├── QUICKSTART.md # Démarrage rapide
├── ARCHITECTURE.md # Ce fichier
└── test-api.sh # Tests API
Flux de Requête
1️⃣ Authentification OIDC
Utilisateur → http://localhost:3000/
↓
Pas d'authentification ?
↓
Redirect → /auth/login
↓
Utilisateur clique "Login"
↓
GET /auth/login
↓
Redirect vers Keycloak Authorization Endpoint
↓
Utilisateur s'authentifie sur Keycloak
↓
Keycloak redirige vers /callback avec code
↓
POST /auth/callback
↓
Exchange code → Token
↓
Récupérer userInfo
↓
Créer session utilisateur
↓
Redirect vers page demandée originalement
2️⃣ Accès à un Service Protégé
Utilisateur (authentifié) → GET /myapp
↓
Trouve service dans DB
↓
Service nécessite auth ?
↓
Utilisateur a session ?
↓
OUI → Proxifier vers target
↓
Utilisateur (anonyme) → GET /public
↓
Service trouvé
↓
Service nécessite auth ?
↓
NON → Proxifier directement
3️⃣ Management Admin
Admin → GET /admin
↓
Vérifier : req.session.user.isAdmin ?
↓
NON → 403 Forbidden
↓
OUI → Servir interface admin.html
↓
Admin clique "+ New Service"
↓
POST /api/services (avec CSRF token)
↓
Valider les données
↓
Insérer dans DB
↓
Log action d'audit
↓
Retourner service créé
↓
Réponse affichée dans l'UI
Flux de Données
Services Table (SQLite)
services {
id VARCHAR PRIMARY KEY -- UUID unique
name VARCHAR UNIQUE -- Nom du service
path VARCHAR UNIQUE -- Chemin public (/myapp)
target_url VARCHAR -- URL cible (http://localhost:8080)
require_auth BOOLEAN -- Authentification requise ?
description TEXT -- Description
enabled BOOLEAN -- Service actif ?
created_at DATETIME -- Date création
updated_at DATETIME -- Date modification
}
Audit Logs Table
audit_logs {
id INTEGER PRIMARY KEY AUTO_INCREMENT
action VARCHAR -- SERVICE_CREATED, UPDATED, DELETED
user_id VARCHAR -- ID Keycloak de l'admin
service_id VARCHAR FK -- Service affecté
ip_address VARCHAR -- IP de l'admin
details JSON -- Détails (données modifiées)
timestamp DATETIME -- Quand
}
Access Logs Table
access_logs {
id INTEGER PRIMARY KEY AUTO_INCREMENT
service_id VARCHAR FK -- Service accédé
user_id VARCHAR -- Utilisateur (si auth)
path VARCHAR -- Chemin complet
method VARCHAR -- GET, POST, etc.
status_code INTEGER -- Code réponse (200, 404, etc.)
response_time_ms INTEGER -- Temps réponse en ms
ip_address VARCHAR -- IP du client
timestamp DATETIME -- Quand
}
Flux de Sécurité
OIDC Flow (Authorization Code)
┌─────────────┐ ┌────────────────┐ ┌──────────────┐
│ Browser │ │ Secure Proxy │ │ Keycloak │
└──────┬──────┘ └────────┬───────┘ └──────┬───────┘
│ │ │
│──GET /auth/login───────►│ │
│ │──GET /auth/authorize│
│ │ (with state, nonce)─►│
│ │ │
│◄────────────────────────────────────────Redirect with code
│ (to /callback) │ │
│ │ │
│──GET /callback?code────►│ │
│ │──POST token───────►│
│ │◄──ID+Access Token──│
│ │ │
│◄────User data in session| │
│ │ │
Rate Limiting & Security
Request → Check IP in rate limit store
↓
Count exceeded ?
↓
OUI → 429 Too Many Requests
↓
NON → Continue
↓
CSRF check (POST/PUT/DELETE)
↓
Security headers added
↓
Request logged
↓
Response sent
Performance & Scalabilité
Optimisations Actuelles
- Reverse Proxy : http-proxy avec streaming
- Rate Limiting : En-mémoire (scalable avec Redis)
- Logs : SQLite (adapté pour small-medium)
- Sessions : File-based (pour dev)
Pour la Production
┌─────────────┐
│ Nginx │ ← Load balancer + SSL termination
└─────┬───────┘
│
├─► [Proxy 1] ←► Redis (sessions)
├─► [Proxy 2] ←► +
└─► [Proxy 3] ←► PostgreSQL (logs & services)
Sécurité en Couches
Couche 1 : Transport
- SSL/TLS avec Nginx
- HSTS headers
Couche 2 : Authentification
- OIDC avec Keycloak
- Sessions sécurisées (httpOnly, sameSite)
Couche 3 : Autorisation
- Vérification admin pour /admin et /api
- Service auth check avant proxy
Couche 4 : Validation
- CSRF tokens
- Input validation sur tous les endpoints
- SQL injections protection (parameterized queries)
Couche 5 : Monitoring
- Audit logs de toutes les actions
- Access logs de tous les services
- Rate limiting anti-DDoS
Extensibilité
Ajouter un Nouveau Middleware
// 1. Créer src/middleware/myMiddleware.js
export function myMiddleware(req, res, next) {
// Your logic
next();
}
// 2. Dans server.js
import { myMiddleware } from './middleware/myMiddleware.js';
app.use(myMiddleware);
Ajouter une Nouvelle Route
// 1. Créer route handler
export function myHandler(req, res) {
res.json({ message: 'Hello' });
}
// 2. Créer route file src/routes/myRoutes.js
const router = express.Router();
router.get('/myendpoint', myHandler);
// 3. Dans server.js
import myRoutes from './routes/myRoutes.js';
app.use('/api/my', myRoutes);
Modifier l'UI Admin
- Éditer
public/admin.html - Ajouter sections, boutons, formulaires
- Le JavaScript charge automatiquement l'API
Architecture modulaire, sécurisée et extensible ✨