# ๐Ÿ”ง Explication technique dรฉtaillรฉe - InnotexBoard ## Table des matiรจres 1. [Architecture systรจme](#architecture) 2. [Authentification PAM + JWT](#authentification) 3. [Gestion Docker](#docker) 4. [Monitoring systรจme](#monitoring) 5. [Frontend et communication API](#frontend) 6. [Sรฉcuritรฉ](#sรฉcuritรฉ) --- ## 1. Architecture systรจme {#architecture} ### Diagramme de flux ``` โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ Navigateur (Frontend) โ”‚ โ”‚ http://localhost:3000 โ”‚ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ โ”‚ Vue.js 3 Application โ”‚ โ”‚ โ”‚ โ”‚ - Pages: Login, Dashboard, Containers โ”‚ โ”‚ โ”‚ โ”‚ - Store Pinia pour l'รฉtat โ”‚ โ”‚ โ”‚ โ”‚ - Axios pour les requรชtes HTTP โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”‚ JWT Bearer Token โ”‚ CORS allowlist โ–ผ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ Backend FastAPI โ”‚ โ”‚ http://localhost:8000 โ”‚ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ โ”‚ /api/v1/auth - Authentification PAM + JWT โ”‚ โ”‚ โ”‚ โ”‚ /api/v1/system - psutil (CPU/RAM/Processus) โ”‚ โ”‚ โ”‚ โ”‚ /api/v1/docker - Docker SDK Python โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”‚ โ”‚ โ–ผ โ–ผ โ–ผ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ PAM โ”‚ โ”‚ psutil โ”‚ โ”‚ Docker โ”‚ โ”‚ /etc/ โ”‚ โ”‚ /proc โ”‚ โ”‚ Socket โ”‚ โ”‚shadow โ”‚ โ”‚ /sys โ”‚ โ”‚ /var/run/ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ ``` ### Communication API ``` Client โ†’ POST /api/v1/auth/login (username, password) โ†“ PAM Authentication โ†“ JWT Token Generated โ†“ Server โ†’ JSON {token, username} Client โ†’ GET /api/v1/system/stats Authorization: Bearer {token} โ†“ Token validation โ†“ psutil data gathering โ†“ Server โ†’ JSON {cpu, memory, processes} ``` --- ## 2. Authentification PAM + JWT {#authentification} ### Fichier principal : [backend/app/core/security.py](backend/app/core/security.py) ### Flux d'authentification ```python # 1. L'utilisateur envoie ses identifiants POST /auth/login { "username": "john", "password": "secret123" } # 2. Backend appelle PAM pam_auth = pam.pam() if pam_auth.authenticate(username, password): # โœ… Identifiants valides # โœ… L'utilisateur existe sur le systรจme # 3. Gรฉnรฉrer un JWT token token = jwt.encode({ "sub": username, "exp": datetime.utcnow() + timedelta(hours=8) }, SECRET_KEY, algorithm="HS256") # 4. Retourner le token return { "access_token": token, "token_type": "bearer", "username": username } else: # โŒ Identifiants invalides raise HTTP 401 Unauthorized ``` ### Validation des requรชtes protรฉgรฉes ```python # Chaque endpoint protรฉgรฉ utilise get_current_user @router.get("/stats") async def get_system_stats(current_user: User = Depends(get_current_user)): # 1. Extraire le token du header Authorization # 2. Dรฉcoder et valider le JWT # 3. Vรฉrifier l'expiration # 4. Retourner l'utilisateur ou lever 401 return system_stats ``` ### Structure du JWT ``` Header: { "alg": "HS256", "typ": "JWT" } Payload: { "sub": "john", # subject (username) "exp": 1704067200, # expiration time "iat": 1704060000 # issued at } Signature: HMAC-SHA256(header.payload, SECRET_KEY) Token final: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... ``` ### Avantages PAM vs alternatives | Aspect | PAM | LDAP | Local DB | |--------|-----|------|----------| | Utilise les utilisateurs systรจme | โœ… | โœ… | โŒ | | Facile ร  configurer | โœ… | โŒ | โœ… | | SSO support | Limitรฉ | โœ… | โŒ | | Groupe systรจme | โœ… | โœ… | โŒ | | Nรฉcessite sudo | โœ… | โŒ | โŒ | --- ## 3. Gestion Docker {#docker} ### Fichier principal : [backend/app/services/docker_service.py](backend/app/services/docker_service.py) ### Initialisation de la connexion ```python import docker class DockerService: def __init__(self): # Se connecter via le socket Docker self.client = docker.from_env() # Equivalent ร : docker.DockerClient(base_url='unix:///var/run/docker.sock') ``` ### Rรฉcupรฉrer les conteneurs ```python def get_containers(self, all=True): """ all=True : obtient tous les conteneurs (running + stopped) all=False : obtient seulement les conteneurs en cours d'exรฉcution """ containers = self.client.containers.list(all=all) for container in containers: # Stats en temps rรฉel stats = container.stats(stream=False) # Extraction CPU cpu_delta = stats['cpu_stats']['cpu_usage']['total_usage'] - \ stats['precpu_stats']['cpu_usage']['total_usage'] system_cpu = stats['cpu_stats']['system_cpu_usage'] - \ stats['precpu_stats']['system_cpu_usage'] cpu_percent = (cpu_delta / system_cpu) * 100.0 # Extraction mรฉmoire memory_mb = stats['memory_stats']['usage'] / (1024*1024) ``` ### Opรฉrations sur les conteneurs ```python # Dรฉmarrer container.start() # Arrรชter (gracieux) container.stop(timeout=10) # Redรฉmarrer container.restart(timeout=10) # Supprimer container.remove(force=False) # force=True pour les containers running ``` ### Permissions Docker requises Pour que le serveur web puisse utiliser Docker, il faut soit : 1. **Groupe docker** (moins sรฉcurisรฉ) ```bash sudo usermod -aG docker www-data ``` 2. **Sudo sans mot de passe** (recommandรฉ) ```bash echo 'www-data ALL=(ALL) NOPASSWD: /usr/bin/docker' | sudo tee /etc/sudoers.d/docker ``` 3. **Socket Docker avec permissions** (avancรฉ) ```bash sudo setfacl -m u:www-data:rw /var/run/docker.sock ``` --- ## 4. Monitoring systรจme {#monitoring} ### Fichier principal : [backend/app/services/system.py](backend/app/services/system.py) ### Utilisation CPU ```python import psutil # CPU % (moyenne sur 1 seconde) cpu_percent = psutil.cpu_percent(interval=1) # Retourne: 45.3 # Nombre de cores cpu_count = psutil.cpu_count() # Retourne: 8 ``` ### Utilisation mรฉmoire ```python memory = psutil.virtual_memory() # memory.percent โ†’ 65.2% # memory.used โ†’ 4GB (en bytes) # memory.total โ†’ 8GB (en bytes) # memory.available โ†’ 2GB (en bytes) ``` ### Processus actifs ```python for proc in psutil.process_iter(['pid', 'name', 'status', 'username']): try: info = proc.info cpu_pct = proc.cpu_percent(interval=0.1) mem_pct = proc.memory_percent() # Rรฉsultat: # { # "pid": 1234, # "name": "python3", # "status": "running", # "username": "www-data", # "cpu_percent": 5.2, # "memory_percent": 0.8 # } except (psutil.NoSuchProcess, psutil.AccessDenied): continue # Accรจs denied pour certains processus ``` ### Points d'accรจs systรจme - `/proc/cpuinfo` โ†’ Info CPU - `/proc/meminfo` โ†’ Info mรฉmoire - `/proc/[pid]/` โ†’ Info processus - `/sys/class/net/` โ†’ Info rรฉseau ### Permissions nรฉcessaires ```bash # psutil lit /proc et /sys, accessible par dรฉfaut ls -la /proc | head # dr-xr-xr-x root root /proc # Certains processus peuvent รชtre inaccessibles # (/proc/[pid]/stat pour processus d'autres utilisateurs) # Solution: lancer avec sudo sudo python main.py # Ou relรขcher les permissions (attention!) sudo chmod 755 /proc ``` --- ## 5. Frontend et communication API {#frontend} ### Architecture Vue 3 ``` App.vue (composant racine) โ”œโ”€โ”€ Navigation (header) โ”œโ”€โ”€ Sidebar (menu) โ””โ”€โ”€ โ”œโ”€โ”€ LoginView.vue (unauthenticated) โ”œโ”€โ”€ DashboardView.vue (authenticated) โ””โ”€โ”€ ContainersView.vue (authenticated) ``` ### Store Pinia ```javascript // stores/auth.js export const useAuthStore = defineStore('auth', () => { // ร‰tat rรฉactif const token = ref(null) const username = ref(null) // Computed const isAuthenticated = computed(() => !!token.value) // Actions async function login(username, password) { const response = await api.post('/auth/login', formData) token.value = response.data.access_token localStorage.setItem('token', token.value) } function logout() { token.value = null localStorage.removeItem('token') } return { token, username, isAuthenticated, login, logout } }) ``` ### Client HTTP avec Axios ```javascript // api/index.js const api = axios.create({ baseURL: 'http://localhost:8000/api/v1', }) // Interceptor de requรชte: ajouter le JWT token api.interceptors.request.use((config) => { const token = localStorage.getItem('token') if (token) { config.headers.Authorization = `Bearer ${token}` } return config }) // Interceptor de rรฉponse: gรฉrer les 401 api.interceptors.response.use( response => response, error => { if (error.response?.status === 401) { // Token expirรฉ, rediriger vers login window.location.href = '/login' } return Promise.reject(error) } ) ``` ### Affichage des donnรฉes ```vue ``` ### Styling Tailwind CSS ```css /* Classes utilitaires utilisรฉes */ .card { @apply bg-gray-800 rounded-lg p-6 shadow-lg border border-gray-700; } .btn-primary { @apply bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg; } /* Design "dark mode" */ body { @apply bg-gray-900 text-gray-100; } ``` --- ## 6. Sรฉcuritรฉ {#sรฉcuritรฉ} ### CORS (Cross-Origin Resource Sharing) ```python # backend/app/core/config.py ALLOWED_ORIGINS: list = [ "http://localhost:3000", # Dev frontend "https://admin.example.com", # Production frontend ] # Appliquรฉ via middleware app.add_middleware( CORSMiddleware, allow_origins=ALLOWED_ORIGINS, allow_methods=["*"], allow_headers=["*"], ) ``` **Importance**: ร‰vite que des sites malveillants fassent des requรชtes ร  votre API ### TrustedHost Middleware ```python app.add_middleware( TrustedHostMiddleware, allowed_hosts=["localhost", "127.0.0.1"], ) ``` **Importance**: Valide l'en-tรชte Host des requรชtes ### Validation Pydantic ```python class LoginRequest(BaseModel): username: str password: str @validator('username') def username_alphanumeric(cls, v): assert v.isalnum() # Seulement alphanumรฉrique return v ``` **Importance**: Valide et parse automatiquement les donnรฉes ### JWT Secrets ```bash # Gรฉnรฉrer une clรฉ sรฉcurisรฉe python3 -c "import secrets; print(secrets.token_urlsafe(32))" # Ajouter au .env SECRET_KEY=your-generated-key-here ``` **Importance**: - Doit รชtre complexe (32+ caractรจres) - Jamais en clair dans le code - Unique par environnement (dev/prod) - Jamais partager ### Protection des endpoints ```python @router.get("/sensitive-data") async def sensitive_endpoint(current_user: User = Depends(get_current_user)): # Cette dรฉpendance valide le token # Lever HTTPException 401 si invalid return data ``` ### Vรฉrification des permissions ```bash # Avant de lancer l'app ls -la /var/run/docker.sock # crw-rw---- root docker /var/run/docker.sock # L'utilisateur du serveur doit รชtre dans le groupe docker id www-data # uid=33(www-data) gid=33(www-data) groups=33(www-data),999(docker) ``` ### Best practices en production 1. โœ… Utiliser HTTPS (TLS/SSL) 2. โœ… Ajouter un reverse proxy (Nginx) 3. โœ… Rate limiting sur les endpoints 4. โœ… Logging des accรจs 5. โœ… Rotation des secrets 6. โœ… Backup de la config 7. โœ… Monitoring de l'uptime 8. โœ… Firewall IP whitelist --- ## ๐Ÿ“Š Rรฉsumรฉ flux de donnรฉes ``` 1. USER LOGIN Client โ†’ Browser โ†’ POST /auth/login โ†’ Backend Backend: PAM auth โ†’ JWT encode โ†’ JSON response Browser: Store token in localStorage 2. API CALL Browser โ†’ GET /system/stats (Header: Authorization: Bearer {token}) Backend: Validate JWT โ†’ Call psutil โ†’ JSON response Browser: Update UI with new data 3. DOCKER ACTION Browser โ†’ POST /docker/containers/{id}/start Backend: Docker.container.start() โ†’ JSON response Browser: Refresh container list 4. AUTO-REFRESH JS Timer every 5 seconds: GET /system/stats โ†’ Update charts GET /docker/containers โ†’ Update list ``` --- ## ๐Ÿ”— Ressources - [PAM Documentation](http://www.linux-pam.org/) - [JWT Introduction](https://jwt.io) - [Docker Python API](https://docker-py.readthedocs.io) - [psutil Documentation](https://psutil.readthedocs.io) - [FastAPI Security](https://fastapi.tiangolo.com/tutorial/security/) - [Vue 3 Composition API](https://vuejs.org/guide/extras/composition-api-faq.html)