From 2697b5fb6b2ec686c1a14c32a2b45e2ac82e843f Mon Sep 17 00:00:00 2001 From: AirKyzzZ Date: Fri, 10 Oct 2025 09:35:15 +0200 Subject: [PATCH] feat(api): JWT auth + update docs --- .gitignore | 5 +- README.md | 643 +++++++++++++++++- composer.json | 1 + composer.lock | 255 ++++++- config/bundles.php | 1 + config/packages/lexik_jwt_authentication.yaml | 5 + config/packages/security.yaml | 33 +- config/routes/security.yaml | 4 + symfony.lock | 12 + 9 files changed, 931 insertions(+), 28 deletions(-) create mode 100644 config/packages/lexik_jwt_authentication.yaml diff --git a/.gitignore b/.gitignore index 8fcb775..7e91ca3 100644 --- a/.gitignore +++ b/.gitignore @@ -36,4 +36,7 @@ composer.phar ###> System Files ### Thumbs.db .DS_Store -###< System Files ### \ No newline at end of file +###< System Files ### +###> lexik/jwt-authentication-bundle ### +/config/jwt/*.pem +###< lexik/jwt-authentication-bundle ### diff --git a/README.md b/README.md index 7de84f8..2368e8d 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,7 @@ Service API backend qui fait le pont entre les applications frontend et la gesti Ce backend agit comme un middleware entre votre application frontend et les serveurs Proxmox VE, offrant : - Points de terminaison API unifiĂ©s pour la gestion des VMs +- **🔐 Authentification JWT sĂ©curisĂ©e** pour protĂ©ger l'accĂšs Ă  l'API - Gestion de l'authentification avec l'API Proxmox - AgrĂ©gation de donnĂ©es depuis plusieurs nƓuds Proxmox - CapacitĂ©s de pagination et de filtrage @@ -18,6 +19,367 @@ Ce backend agit comme un middleware entre votre application frontend et les serv - Symfony 7.x - AccĂšs Ă  l'API Proxmox VE (v6.x ou v7.x) +## đŸ–„ïž Configuration d'une VM Linux pour HĂ©berger le Backend + +Cette section dĂ©taille les dĂ©pendances et configurations nĂ©cessaires pour crĂ©er une machine virtuelle Linux qui hĂ©bergera ce backend et fera le lien entre les machines Proxmox et le frontend. + +### SpĂ©cifications RecommandĂ©es de la VM + +**Configuration Minimale :** +- **OS** : Ubuntu 22.04 LTS / Debian 12 / Rocky Linux 9 +- **CPU** : 2 vCPUs +- **RAM** : 2 GB minimum (4 GB recommandĂ©) +- **Disque** : 20 GB minimum (50 GB recommandĂ©) +- **RĂ©seau** : Interface rĂ©seau avec accĂšs Ă  Proxmox et au frontend + +**Configuration pour Production :** +- **CPU** : 4+ vCPUs +- **RAM** : 8 GB+ +- **Disque** : 100 GB+ (SSD recommandĂ©) +- **RĂ©seau** : Interface rĂ©seau avec IP statique + +### DĂ©pendances SystĂšme Ă  Installer + +#### 1. Mise Ă  Jour du SystĂšme + +```bash +# Pour Ubuntu/Debian +sudo apt update && sudo apt upgrade -y + +# Pour Rocky Linux/RHEL +sudo dnf update -y +``` + +#### 2. Installation de PHP 8.2+ + +**Ubuntu/Debian :** +```bash +# Ajouter le dĂ©pĂŽt PPA pour PHP 8.2+ +sudo apt install software-properties-common -y +sudo add-apt-repository ppa:ondrej/php -y +sudo apt update + +# Installer PHP 8.2 et les extensions requises +sudo apt install -y \ + php8.2 \ + php8.2-cli \ + php8.2-fpm \ + php8.2-common \ + php8.2-curl \ + php8.2-mbstring \ + php8.2-xml \ + php8.2-zip \ + php8.2-intl \ + php8.2-opcache \ + php8.2-ctype \ + php8.2-iconv + +# VĂ©rifier la version +php -v +``` + +**Rocky Linux/RHEL :** +```bash +# Activer le dĂ©pĂŽt EPEL et Remi +sudo dnf install -y epel-release +sudo dnf install -y https://rpms.remirepo.net/enterprise/remi-release-9.rpm + +# Activer PHP 8.2 +sudo dnf module reset php -y +sudo dnf module enable php:remi-8.2 -y + +# Installer PHP et les extensions +sudo dnf install -y \ + php \ + php-cli \ + php-fpm \ + php-common \ + php-curl \ + php-mbstring \ + php-xml \ + php-zip \ + php-intl \ + php-opcache + +# VĂ©rifier la version +php -v +``` + +#### 3. Installation de Composer + +```bash +# TĂ©lĂ©charger l'installateur +php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" + +# VĂ©rifier l'installateur (optionnel) +php -r "if (hash_file('sha384', 'composer-setup.php') === file_get_contents('https://composer.github.io/installer.sig')) { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" + +# Installer Composer globalement +sudo php composer-setup.php --install-dir=/usr/local/bin --filename=composer + +# Nettoyer +php -r "unlink('composer-setup.php');" + +# VĂ©rifier l'installation +composer --version +``` + +#### 4. Installation d'un Serveur Web + +**Option A : Nginx (RecommandĂ© pour la Production)** + +```bash +# Ubuntu/Debian +sudo apt install -y nginx + +# Rocky Linux/RHEL +sudo dnf install -y nginx + +# DĂ©marrer et activer Nginx +sudo systemctl start nginx +sudo systemctl enable nginx +``` + +**Configuration Nginx pour Symfony :** + +```bash +sudo nano /etc/nginx/sites-available/managevmback +``` + +Contenu du fichier : +```nginx +server { + listen 80; + server_name votre-domaine.com; # Remplacer par votre domaine ou IP + root /var/www/ManageVMBack/public; + + location / { + try_files $uri /index.php$is_args$args; + } + + location ~ ^/index\.php(/|$) { + fastcgi_pass unix:/var/run/php/php8.2-fpm.sock; + fastcgi_split_path_info ^(.+\.php)(/.*)$; + include fastcgi_params; + fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; + fastcgi_param DOCUMENT_ROOT $realpath_root; + internal; + } + + location ~ \.php$ { + return 404; + } + + error_log /var/log/nginx/managevmback_error.log; + access_log /var/log/nginx/managevmback_access.log; +} +``` + +```bash +# Activer le site +sudo ln -s /etc/nginx/sites-available/managevmback /etc/nginx/sites-enabled/ + +# Tester la configuration +sudo nginx -t + +# Recharger Nginx +sudo systemctl reload nginx +``` + +**Option B : Apache** + +```bash +# Ubuntu/Debian +sudo apt install -y apache2 libapache2-mod-php8.2 + +# Rocky Linux/RHEL +sudo dnf install -y httpd + +# Activer les modules nĂ©cessaires +sudo a2enmod rewrite +sudo a2enmod php8.2 + +# DĂ©marrer et activer Apache +sudo systemctl start apache2 # ou httpd pour Rocky Linux +sudo systemctl enable apache2 +``` + +#### 5. Outils SystĂšme SupplĂ©mentaires + +```bash +# Ubuntu/Debian +sudo apt install -y \ + git \ + curl \ + wget \ + unzip \ + vim \ + net-tools \ + ca-certificates + +# Rocky Linux/RHEL +sudo dnf install -y \ + git \ + curl \ + wget \ + unzip \ + vim \ + net-tools \ + ca-certificates +``` + +#### 6. Configuration SSL/TLS (Optionnel mais RecommandĂ©) + +```bash +# Installer Certbot pour Let's Encrypt +# Ubuntu/Debian +sudo apt install -y certbot python3-certbot-nginx + +# Rocky Linux/RHEL +sudo dnf install -y certbot python3-certbot-nginx + +# Obtenir un certificat SSL +sudo certbot --nginx -d votre-domaine.com + +# Le renouvellement automatique est configurĂ© par dĂ©faut +sudo systemctl status certbot.timer +``` + +#### 7. Configuration du Pare-feu + +```bash +# UFW (Ubuntu/Debian) +sudo ufw allow 22/tcp # SSH +sudo ufw allow 80/tcp # HTTP +sudo ufw allow 443/tcp # HTTPS +sudo ufw enable + +# FirewallD (Rocky Linux/RHEL) +sudo firewall-cmd --permanent --add-service=ssh +sudo firewall-cmd --permanent --add-service=http +sudo firewall-cmd --permanent --add-service=https +sudo firewall-cmd --reload +``` + +#### 8. Optimisation PHP pour Production + +Éditer le fichier `php.ini` : +```bash +sudo nano /etc/php/8.2/fpm/php.ini # Ubuntu/Debian +# ou +sudo nano /etc/php.ini # Rocky Linux/RHEL +``` + +ParamĂštres recommandĂ©s : +```ini +memory_limit = 256M +max_execution_time = 30 +upload_max_filesize = 20M +post_max_size = 20M +opcache.enable = 1 +opcache.memory_consumption = 128 +opcache.max_accelerated_files = 10000 +opcache.revalidate_freq = 60 +``` + +RedĂ©marrer PHP-FPM : +```bash +sudo systemctl restart php8.2-fpm # Ubuntu/Debian +sudo systemctl restart php-fpm # Rocky Linux/RHEL +``` + +#### 9. Configuration des Permissions + +```bash +# CrĂ©er un utilisateur dĂ©diĂ© pour l'application (optionnel) +sudo useradd -m -s /bin/bash vmbackend + +# CrĂ©er le rĂ©pertoire de l'application +sudo mkdir -p /var/www/ManageVMBack +sudo chown -R www-data:www-data /var/www/ManageVMBack # Ubuntu/Debian +# ou +sudo chown -R nginx:nginx /var/www/ManageVMBack # Rocky Linux/RHEL + +# DĂ©finir les permissions appropriĂ©es +sudo chmod -R 755 /var/www/ManageVMBack +``` + +### Configuration RĂ©seau + +#### Connexion Ă  Proxmox + +Assurez-vous que la VM peut atteindre les serveurs Proxmox : + +```bash +# Tester la connectivitĂ© +curl -k https://votre-serveur-proxmox:8006 + +# VĂ©rifier la rĂ©solution DNS +nslookup votre-serveur-proxmox +``` + +#### Autoriser les Connexions Frontend + +Configurez le pare-feu pour autoriser les connexions depuis le frontend : + +```bash +# Si le frontend a une IP fixe +sudo ufw allow from IP_DU_FRONTEND to any port 80 +sudo ufw allow from IP_DU_FRONTEND to any port 443 +``` + +### Liste de ContrĂŽle Finale + +Avant de dĂ©ployer l'application, vĂ©rifiez : + +- [ ] PHP 8.2+ installĂ© avec toutes les extensions requises +- [ ] Composer installĂ© et accessible globalement +- [ ] Serveur web (Nginx/Apache) installĂ© et configurĂ© +- [ ] PHP-FPM configurĂ© et en cours d'exĂ©cution +- [ ] Pare-feu configurĂ© (ports 80/443 ouverts) +- [ ] Permissions correctes sur les rĂ©pertoires +- [ ] Connexion rĂ©seau vers Proxmox fonctionnelle +- [ ] CORS configurĂ© pour le frontend +- [ ] SSL/TLS configurĂ© (pour la production) +- [ ] Sauvegardes automatiques configurĂ©es (optionnel) + +### Surveillance et Logs + +Emplacements des logs importants : + +```bash +# Logs Nginx +/var/log/nginx/managevmback_error.log +/var/log/nginx/managevmback_access.log + +# Logs Apache +/var/log/apache2/error.log # Ubuntu/Debian +/var/log/httpd/error_log # Rocky Linux/RHEL + +# Logs PHP-FPM +/var/log/php8.2-fpm.log # Ubuntu/Debian +/var/log/php-fpm/error.log # Rocky Linux/RHEL + +# Logs de l'application Symfony +/var/www/ManageVMBack/var/log/prod.log +/var/www/ManageVMBack/var/log/dev.log +``` + +Commandes utiles pour surveiller : +```bash +# Surveiller les logs en temps rĂ©el +sudo tail -f /var/log/nginx/managevmback_error.log + +# VĂ©rifier l'Ă©tat des services +sudo systemctl status nginx +sudo systemctl status php8.2-fpm + +# VĂ©rifier l'utilisation des ressources +htop +free -h +df -h +``` + ## 🚀 Installation ### 1. Cloner le dĂ©pĂŽt @@ -89,7 +451,44 @@ Au lieu d'utiliser nom d'utilisateur/mot de passe, vous pouvez utiliser des toke # PROXMOX_TOKEN_SECRET=your-token-secret ``` -### 5. Vider le cache +### 5. Configuration JWT (Authentification) + +Ce backend utilise JWT (JSON Web Tokens) pour sĂ©curiser l'API. Les clĂ©s JWT ont dĂ©jĂ  Ă©tĂ© gĂ©nĂ©rĂ©es lors de l'installation. + +**VĂ©rifier que les clĂ©s JWT existent :** +```bash +ls -la config/jwt/ +# Vous devriez voir : private.pem et public.pem +``` + +**Si les clĂ©s n'existent pas, gĂ©nĂ©rez-les :** +```bash +php bin/console lexik:jwt:generate-keypair +``` + +**Configuration des variables d'environnement JWT :** + +Les variables suivantes sont automatiquement configurĂ©es dans `.env` : +```env +###> lexik/jwt-authentication-bundle ### +JWT_SECRET_KEY=%kernel.project_dir%/config/jwt/private.pem +JWT_PUBLIC_KEY=%kernel.project_dir%/config/jwt/public.pem +JWT_PASSPHRASE=your_passphrase_here +###< lexik/jwt-authentication-bundle ### +``` + +**Utilisateurs de test configurĂ©s :** + +Pour le dĂ©veloppement, deux utilisateurs sont prĂ©configurĂ©s dans `config/packages/security.yaml` : + +| Username | Password | Roles | +|----------|----------|-------| +| `admin` | `admin123` | ROLE_ADMIN, ROLE_USER | +| `user` | `user123` | ROLE_USER | + +⚠ **Important** : En production, remplacez ces utilisateurs par une vraie base de donnĂ©es utilisateurs ! + +### 6. Vider le cache ```bash php bin/console cache:clear @@ -122,12 +521,100 @@ Pour le dĂ©ploiement en production, utilisez un serveur web appropriĂ© (Apache/N http://localhost:8000/api/v1 ``` +### 🔐 Authentification JWT + +Tous les endpoints API (sauf `/api/login_check`) nĂ©cessitent une authentification JWT. + +#### Obtenir un Token JWT + +**Endpoint :** `POST /api/login_check` + +**RequĂȘte :** +```bash +curl -X POST http://localhost:8000/api/login_check \ + -H "Content-Type: application/json" \ + -d '{ + "username": "admin", + "password": "admin123" + }' +``` + +**RĂ©ponse :** +```json +{ + "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9..." +} +``` + +Le token est valide pendant **1 heure** (3600 secondes). + +#### Utiliser le Token JWT + +Incluez le token dans l'en-tĂȘte `Authorization` avec le prĂ©fixe `Bearer` : + +```bash +curl -H "Authorization: Bearer VOTRE_TOKEN_ICI" \ + http://localhost:8000/api/v1/vms +``` + +**Exemple complet :** +```bash +# 1. Obtenir le token +TOKEN=$(curl -s -X POST http://localhost:8000/api/login_check \ + -H "Content-Type: application/json" \ + -d '{"username":"admin","password":"admin123"}' \ + | jq -r '.token') + +# 2. Utiliser le token pour accĂ©der Ă  l'API +curl -H "Authorization: Bearer $TOKEN" \ + http://localhost:8000/api/v1/vms +``` + +**JavaScript/Frontend :** +```javascript +// 1. Login +const response = await fetch('http://localhost:8000/api/login_check', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + username: 'admin', + password: 'admin123' + }) +}); + +const { token } = await response.json(); + +// 2. Stocker le token (localStorage, sessionStorage, ou cookie sĂ©curisĂ©) +localStorage.setItem('jwt_token', token); + +// 3. Utiliser le token dans les requĂȘtes suivantes +const vmsResponse = await fetch('http://localhost:8000/api/v1/vms', { + headers: { + 'Authorization': `Bearer ${token}` + } +}); + +const vms = await vmsResponse.json(); +``` + +**Gestion des erreurs JWT :** + +| Code | Message | Signification | +|------|---------|---------------| +| 401 | JWT Token not found | Token manquant dans l'en-tĂȘte Authorization | +| 401 | Invalid JWT Token | Token invalide ou malformĂ© | +| 401 | Expired JWT Token | Token expirĂ© (> 1 heure) | +| 401 | Invalid credentials | Username ou password incorrect | + ### RĂ©fĂ©rence Rapide | CatĂ©gorie | MĂ©thode | Endpoint | Description | |-----------|---------|----------|-------------| -| **VMs** | GET | `/api/v1/vms` | Lister toutes les VMs (avec filtres) | -| | GET | `/api/v1/vms/{node}/{vmid}` | Obtenir les dĂ©tails d'une VM | +| **Authentification** | POST | `/api/login_check` | 🔓 Obtenir un token JWT (pas d'auth requise) | +| **VMs** | GET | `/api/v1/vms` | 🔒 Lister toutes les VMs (avec filtres) | +| | GET | `/api/v1/vms/{node}/{vmid}` | 🔒 Obtenir les dĂ©tails d'une VM | | **ContrĂŽle VM SimplifiĂ©** | POST | `/api/v1/vms/{vmid}/start` | ⭐ DĂ©marrer une VM (dĂ©tection auto du nƓud) | | | POST | `/api/v1/vms/{vmid}/stop` | ⭐ ArrĂȘter une VM avec mode (acpi/hard) | | **Snapshots** | GET | `/api/v1/vms/{vmid}/snapshots` | Lister les snapshots d'une VM | @@ -686,6 +1173,8 @@ tail -f var/log/dev.log ## 🔒 ConsidĂ©rations de SĂ©curitĂ© +### SĂ©curitĂ© GĂ©nĂ©rale + 1. **Ne jamais commiter le fichier `.env`** - Il contient des identifiants sensibles 2. **Utiliser des tokens API au lieu de mots de passe** en production 3. **Activer la vĂ©rification SSL** (`PROXMOX_VERIFY_SSL=true`) avec des certificats valides @@ -693,6 +1182,54 @@ tail -f var/log/dev.log 5. **Changer `APP_SECRET`** pour une valeur alĂ©atoire en production 6. **Restreindre les permissions utilisateur Proxmox** - CrĂ©er un utilisateur dĂ©diĂ© avec les permissions minimales requises +### SĂ©curitĂ© JWT + +1. **ProtĂ©ger les clĂ©s JWT** : + - Les fichiers `config/jwt/private.pem` et `config/jwt/public.pem` sont critiques + - Ne jamais commiter ces fichiers dans Git (dĂ©jĂ  dans `.gitignore`) + - En production, stocker la clĂ© privĂ©e de maniĂšre sĂ©curisĂ©e (variables d'environnement, vault, etc.) + - Permissions recommandĂ©es : `chmod 600 config/jwt/private.pem` + +2. **Configurer une passphrase forte** : + ```bash + # Dans .env, dĂ©finir une passphrase forte + JWT_PASSPHRASE=VotrePassphraseComplexeEtSecurisee123!@# + ``` + +3. **GĂ©rer l'expiration des tokens** : + - Par dĂ©faut : 1 heure (`token_ttl: 3600` dans `config/packages/lexik_jwt_authentication.yaml`) + - Ajuster selon vos besoins de sĂ©curitĂ© + - ImplĂ©menter un systĂšme de refresh tokens pour les sessions longues + +4. **Remplacer les utilisateurs en mĂ©moire en production** : + - Les utilisateurs actuels (`admin`, `user`) sont pour le dĂ©veloppement uniquement + - CrĂ©er une entitĂ© User avec Doctrine pour la production + - Exemple de crĂ©ation d'entitĂ© User : + ```bash + php bin/console make:user + php bin/console make:migration + php bin/console doctrine:migrations:migrate + ``` + +5. **Transmission sĂ©curisĂ©e** : + - Toujours utiliser HTTPS en production + - Les tokens JWT ne doivent jamais ĂȘtre exposĂ©s dans les URLs + - Stocker les tokens cĂŽtĂ© client de maniĂšre sĂ©curisĂ©e (httpOnly cookies recommandĂ©s) + +6. **Validation cĂŽtĂ© serveur** : + - Les tokens sont automatiquement validĂ©s par le bundle + - VĂ©rifier les rĂŽles utilisateur dans vos contrĂŽleurs si nĂ©cessaire : + ```php + $this->denyAccessUnlessGranted('ROLE_ADMIN'); + ``` + +7. **Rotation des clĂ©s** : + - En cas de compromission, regĂ©nĂ©rer les clĂ©s : + ```bash + php bin/console lexik:jwt:generate-keypair --overwrite + ``` + - Tous les tokens existants seront invalides aprĂšs la rotation + ### Permissions Proxmox RecommandĂ©es CrĂ©er un utilisateur/rĂŽle dĂ©diĂ© pour l'API avec uniquement les permissions requises : @@ -746,6 +1283,44 @@ Si vous obtenez "VM with ID {vmid} not found on any node" : 2. VĂ©rifiez que l'utilisateur a les permissions pour voir cette VM 3. VĂ©rifiez que la VM n'est pas un conteneur LXC (cette API gĂšre uniquement les VMs QEMU) +### ProblĂšmes JWT + +**"JWT Token not found"** +- VĂ©rifiez que vous incluez l'en-tĂȘte : `Authorization: Bearer VOTRE_TOKEN` +- VĂ©rifiez qu'il n'y a pas d'espace supplĂ©mentaire dans l'en-tĂȘte + +**"Invalid JWT Token"** +- Le token est malformĂ© ou corrompu +- Obtenez un nouveau token via `/api/login_check` + +**"Expired JWT Token"** +- Le token a expirĂ© (durĂ©e de vie : 1 heure) +- Obtenez un nouveau token via `/api/login_check` + +**"Invalid credentials"** +- Username ou password incorrect +- VĂ©rifiez les utilisateurs configurĂ©s dans `config/packages/security.yaml` +- Credentials par dĂ©faut : `admin` / `admin123` ou `user` / `user123` + +**Les clĂ©s JWT n'existent pas** +```bash +# GĂ©nĂ©rer les clĂ©s +php bin/console lexik:jwt:generate-keypair + +# VĂ©rifier les permissions +chmod 600 config/jwt/private.pem +chmod 644 config/jwt/public.pem +``` + +**Route `/api/login_check` not found** +```bash +# Vider le cache +php bin/console cache:clear + +# VĂ©rifier les routes +php bin/console debug:router | grep login +``` + ## 📝 Ajout de Nouvelles FonctionnalitĂ©s ### Ajouter de Nouvelles OpĂ©rations VM @@ -780,39 +1355,77 @@ php bin/console cache:clear ## đŸ§Ș Tests +### Tester l'Authentification JWT + +```bash +# 1. Tester l'accĂšs sans authentification (devrait Ă©chouer avec 401) +curl http://localhost:8000/api/v1/vms +# RĂ©ponse attendue : {"code":401,"message":"JWT Token not found"} + +# 2. Obtenir un token JWT +curl -X POST http://localhost:8000/api/login_check \ + -H "Content-Type: application/json" \ + -d '{"username":"admin","password":"admin123"}' +# RĂ©ponse attendue : {"token":"eyJ0eXAiOiJKV1QiLCJ..."} + +# 3. Tester avec un token valide +TOKEN="VOTRE_TOKEN_ICI" +curl -H "Authorization: Bearer $TOKEN" http://localhost:8000/api/v1/vms +# Devrait retourner la liste des VMs (ou une erreur Proxmox si non configurĂ©) + +# 4. Tester avec des credentials invalides +curl -X POST http://localhost:8000/api/login_check \ + -H "Content-Type: application/json" \ + -d '{"username":"admin","password":"mauvais_password"}' +# RĂ©ponse attendue : {"code":401,"message":"Invalid credentials."} +``` + ### Tester les Endpoints ```bash -# Tester la santĂ© +# Tester la santĂ© (pas d'authentification requise) curl http://localhost:8000/health -# Tester la disponibilitĂ© +# Tester la disponibilitĂ© (pas d'authentification requise) curl http://localhost:8000/ready -# Lister les VMs -curl "http://localhost:8000/api/v1/vms?state=running" +# Obtenir un token et le stocker +TOKEN=$(curl -s -X POST http://localhost:8000/api/login_check \ + -H "Content-Type: application/json" \ + -d '{"username":"admin","password":"admin123"}' \ + | jq -r '.token') + +# Lister les VMs (avec authentification) +curl -H "Authorization: Bearer $TOKEN" \ + "http://localhost:8000/api/v1/vms?state=running" # DĂ©marrer une VM -curl -X POST http://localhost:8000/api/v1/vms/100/start +curl -X POST -H "Authorization: Bearer $TOKEN" \ + http://localhost:8000/api/v1/vms/100/start # ArrĂȘter une VM (gracieux) -curl -X POST http://localhost:8000/api/v1/vms/100/stop \ +curl -X POST -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ - -d '{"mode": "acpi"}' + -d '{"mode": "acpi"}' \ + http://localhost:8000/api/v1/vms/100/stop # Lister les snapshots -curl http://localhost:8000/api/v1/vms/100/snapshots +curl -H "Authorization: Bearer $TOKEN" \ + http://localhost:8000/api/v1/vms/100/snapshots # CrĂ©er un snapshot -curl -X POST http://localhost:8000/api/v1/vms/100/snapshot \ +curl -X POST -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ - -d '{"name": "test-snapshot", "description": "Test"}' + -d '{"name": "test-snapshot", "description": "Test"}' \ + http://localhost:8000/api/v1/vms/100/snapshot # Revenir Ă  un snapshot -curl -X POST http://localhost:8000/api/v1/vms/100/snapshot/test-snapshot/rollback +curl -X POST -H "Authorization: Bearer $TOKEN" \ + http://localhost:8000/api/v1/vms/100/snapshot/test-snapshot/rollback # Flux d'Ă©vĂ©nements (garder ouvert) -curl http://localhost:8000/api/v1/events/stream +curl -H "Authorization: Bearer $TOKEN" \ + http://localhost:8000/api/v1/events/stream ``` ## 🚀 DĂ©ploiement diff --git a/composer.json b/composer.json index 7346f6a..42e411b 100644 --- a/composer.json +++ b/composer.json @@ -13,6 +13,7 @@ "doctrine/doctrine-bundle": "^2.16", "doctrine/doctrine-migrations-bundle": "^3.4", "doctrine/orm": "^3.5", + "lexik/jwt-authentication-bundle": "^3.1", "nelmio/cors-bundle": "^2.5", "phpdocumentor/reflection-docblock": "^5.6", "phpstan/phpdoc-parser": "^2.3", diff --git a/composer.lock b/composer.lock index 29375b7..47bdf61 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "06674063e9389d880088cfe19341415f", + "content-hash": "4420a83d7246ceb3684b7aceec3e8511", "packages": [ { "name": "api-platform/doctrine-common", @@ -2370,6 +2370,259 @@ }, "time": "2025-01-24T11:45:48+00:00" }, + { + "name": "lcobucci/clock", + "version": "3.4.0", + "source": { + "type": "git", + "url": "https://github.com/lcobucci/clock.git", + "reference": "f91d84f65cb3e974988bbe872b5da8ca132a155f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/lcobucci/clock/zipball/f91d84f65cb3e974988bbe872b5da8ca132a155f", + "reference": "f91d84f65cb3e974988bbe872b5da8ca132a155f", + "shasum": "" + }, + "require": { + "php": "~8.3.0 || ~8.4.0", + "psr/clock": "^1.0" + }, + "provide": { + "psr/clock-implementation": "1.0" + }, + "require-dev": { + "infection/infection": "^0.31", + "lcobucci/coding-standard": "^11.1.0", + "phpstan/extension-installer": "^1.3.1", + "phpstan/phpstan": "^2.0.0", + "phpstan/phpstan-deprecation-rules": "^2.0.0", + "phpstan/phpstan-phpunit": "^2.0.0", + "phpstan/phpstan-strict-rules": "^2.0.0", + "phpunit/phpunit": "^12.0.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Lcobucci\\Clock\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "LuĂ­s Cobucci", + "email": "lcobucci@gmail.com" + } + ], + "description": "Yet another clock abstraction", + "support": { + "issues": "https://github.com/lcobucci/clock/issues", + "source": "https://github.com/lcobucci/clock/tree/3.4.0" + }, + "funding": [ + { + "url": "https://github.com/lcobucci", + "type": "github" + }, + { + "url": "https://www.patreon.com/lcobucci", + "type": "patreon" + } + ], + "time": "2025-10-08T18:00:48+00:00" + }, + { + "name": "lcobucci/jwt", + "version": "5.5.0", + "source": { + "type": "git", + "url": "https://github.com/lcobucci/jwt.git", + "reference": "a835af59b030d3f2967725697cf88300f579088e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/lcobucci/jwt/zipball/a835af59b030d3f2967725697cf88300f579088e", + "reference": "a835af59b030d3f2967725697cf88300f579088e", + "shasum": "" + }, + "require": { + "ext-openssl": "*", + "ext-sodium": "*", + "php": "~8.2.0 || ~8.3.0 || ~8.4.0", + "psr/clock": "^1.0" + }, + "require-dev": { + "infection/infection": "^0.29", + "lcobucci/clock": "^3.2", + "lcobucci/coding-standard": "^11.0", + "phpbench/phpbench": "^1.2", + "phpstan/extension-installer": "^1.2", + "phpstan/phpstan": "^1.10.7", + "phpstan/phpstan-deprecation-rules": "^1.1.3", + "phpstan/phpstan-phpunit": "^1.3.10", + "phpstan/phpstan-strict-rules": "^1.5.0", + "phpunit/phpunit": "^11.1" + }, + "suggest": { + "lcobucci/clock": ">= 3.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "Lcobucci\\JWT\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "LuĂ­s Cobucci", + "email": "lcobucci@gmail.com", + "role": "Developer" + } + ], + "description": "A simple library to work with JSON Web Token and JSON Web Signature", + "keywords": [ + "JWS", + "jwt" + ], + "support": { + "issues": "https://github.com/lcobucci/jwt/issues", + "source": "https://github.com/lcobucci/jwt/tree/5.5.0" + }, + "funding": [ + { + "url": "https://github.com/lcobucci", + "type": "github" + }, + { + "url": "https://www.patreon.com/lcobucci", + "type": "patreon" + } + ], + "time": "2025-01-26T21:29:45+00:00" + }, + { + "name": "lexik/jwt-authentication-bundle", + "version": "v3.1.1", + "source": { + "type": "git", + "url": "https://github.com/lexik/LexikJWTAuthenticationBundle.git", + "reference": "ebe0e2c6a0ae17b4702feffc89e32e3aaba6cb61" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/lexik/LexikJWTAuthenticationBundle/zipball/ebe0e2c6a0ae17b4702feffc89e32e3aaba6cb61", + "reference": "ebe0e2c6a0ae17b4702feffc89e32e3aaba6cb61", + "shasum": "" + }, + "require": { + "ext-openssl": "*", + "lcobucci/clock": "^3.0", + "lcobucci/jwt": "^5.0", + "php": ">=8.2", + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/deprecation-contracts": "^2.4|^3.0", + "symfony/event-dispatcher": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/property-access": "^6.4|^7.0", + "symfony/security-bundle": "^6.4|^7.0", + "symfony/translation-contracts": "^1.0|^2.0|^3.0" + }, + "require-dev": { + "api-platform/core": "^3.0|^4.0", + "rector/rector": "^1.2", + "symfony/browser-kit": "^6.4|^7.0", + "symfony/console": "^6.4|^7.0", + "symfony/dom-crawler": "^6.4|^7.0", + "symfony/filesystem": "^6.4|^7.0", + "symfony/framework-bundle": "^6.4|^7.0", + "symfony/phpunit-bridge": "^6.4|^7.0", + "symfony/var-dumper": "^6.4|^7.0", + "symfony/yaml": "^6.4|^7.0" + }, + "suggest": { + "gesdinet/jwt-refresh-token-bundle": "Implements a refresh token system over Json Web Tokens in Symfony", + "spomky-labs/lexik-jose-bridge": "Provides a JWT Token encoder with encryption support" + }, + "type": "symfony-bundle", + "autoload": { + "psr-4": { + "Lexik\\Bundle\\JWTAuthenticationBundle\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jeremy Barthe", + "email": "j.barthe@lexik.fr", + "homepage": "https://github.com/jeremyb" + }, + { + "name": "Nicolas Cabot", + "email": "n.cabot@lexik.fr", + "homepage": "https://github.com/slashfan" + }, + { + "name": "Cedric Girard", + "email": "c.girard@lexik.fr", + "homepage": "https://github.com/cedric-g" + }, + { + "name": "Dev Lexik", + "email": "dev@lexik.fr", + "homepage": "https://github.com/lexik" + }, + { + "name": "Robin Chalas", + "email": "robin.chalas@gmail.com", + "homepage": "https://github.com/chalasr" + }, + { + "name": "Lexik Community", + "homepage": "https://github.com/lexik/LexikJWTAuthenticationBundle/graphs/contributors" + } + ], + "description": "This bundle provides JWT authentication for your Symfony REST API", + "homepage": "https://github.com/lexik/LexikJWTAuthenticationBundle", + "keywords": [ + "Authentication", + "JWS", + "api", + "bundle", + "jwt", + "rest", + "symfony" + ], + "support": { + "issues": "https://github.com/lexik/LexikJWTAuthenticationBundle/issues", + "source": "https://github.com/lexik/LexikJWTAuthenticationBundle/tree/v3.1.1" + }, + "funding": [ + { + "url": "https://github.com/chalasr", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/lexik/jwt-authentication-bundle", + "type": "tidelift" + } + ], + "time": "2025-01-06T16:34:57+00:00" + }, { "name": "nelmio/cors-bundle", "version": "2.5.0", diff --git a/config/bundles.php b/config/bundles.php index ccc600f..01e362c 100644 --- a/config/bundles.php +++ b/config/bundles.php @@ -8,4 +8,5 @@ Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true], Nelmio\CorsBundle\NelmioCorsBundle::class => ['all' => true], ApiPlatform\Symfony\Bundle\ApiPlatformBundle::class => ['all' => true], + Lexik\Bundle\JWTAuthenticationBundle\LexikJWTAuthenticationBundle::class => ['all' => true], ]; diff --git a/config/packages/lexik_jwt_authentication.yaml b/config/packages/lexik_jwt_authentication.yaml new file mode 100644 index 0000000..d7b6820 --- /dev/null +++ b/config/packages/lexik_jwt_authentication.yaml @@ -0,0 +1,5 @@ +lexik_jwt_authentication: + secret_key: '%env(resolve:JWT_SECRET_KEY)%' + public_key: '%env(resolve:JWT_PUBLIC_KEY)%' + pass_phrase: '%env(JWT_PASSPHRASE)%' + token_ttl: 3600 \ No newline at end of file diff --git a/config/packages/security.yaml b/config/packages/security.yaml index 367af25..fed5d94 100644 --- a/config/packages/security.yaml +++ b/config/packages/security.yaml @@ -4,26 +4,37 @@ security: Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'auto' # https://symfony.com/doc/current/security.html#loading-the-user-the-user-provider providers: - users_in_memory: { memory: null } + users_in_memory: + memory: + users: + admin: + password: '$2y$13$ptRK1Npa7jqV281tFNGEYuFLqC1kSdbJy2No463bmTn4ZO4n12HAO' # password: admin123 + roles: ['ROLE_ADMIN', 'ROLE_USER'] + user: + password: '$2y$13$T/6QQGM2272Oin2e9qcIyedh.m8WXLsgKYMX7QZuDrNKCOzEMbpCW' # password: user123 + roles: ['ROLE_USER'] firewalls: dev: pattern: ^/(_(profiler|wdt)|css|images|js)/ security: false - main: - lazy: true - provider: users_in_memory + login: + pattern: ^/api/login + stateless: true + json_login: + check_path: /api/login_check + success_handler: lexik_jwt_authentication.handler.authentication_success + failure_handler: lexik_jwt_authentication.handler.authentication_failure - # activate different ways to authenticate - # https://symfony.com/doc/current/security.html#the-firewall - - # https://symfony.com/doc/current/security/impersonating_user.html - # switch_user: true + api: + pattern: ^/api + stateless: true + jwt: ~ # Easy way to control access for large sections of your site # Note: Only the *first* access control that matches will be used access_control: - # - { path: ^/admin, roles: ROLE_ADMIN } - # - { path: ^/profile, roles: ROLE_USER } + - { path: ^/api/login, roles: PUBLIC_ACCESS } + - { path: ^/api, roles: IS_AUTHENTICATED_FULLY } when@test: security: diff --git a/config/routes/security.yaml b/config/routes/security.yaml index f853be1..4320527 100644 --- a/config/routes/security.yaml +++ b/config/routes/security.yaml @@ -1,3 +1,7 @@ +api_login_check: + path: /api/login_check + methods: [POST] + _security_logout: resource: security.route_loader.logout type: service diff --git a/symfony.lock b/symfony.lock index 80deac0..ab8e492 100644 --- a/symfony.lock +++ b/symfony.lock @@ -49,6 +49,18 @@ "migrations/.gitignore" ] }, + "lexik/jwt-authentication-bundle": { + "version": "3.1", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "2.5", + "ref": "e9481b233a11ef7e15fe055a2b21fd3ac1aa2bb7" + }, + "files": [ + "config/packages/lexik_jwt_authentication.yaml" + ] + }, "nelmio/cors-bundle": { "version": "2.5", "recipe": {