proxy-oidcv2/ARCHITECTURE.md
2025-12-03 21:34:44 +01:00

14 KiB
Raw Permalink Blame History

📐 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