refactorisation pour correction de sécurité
Tests / Backend Tests (Python) (3.10) (push) Has been cancelled
Tests / Backend Tests (Python) (3.11) (push) Has been cancelled
Tests / Backend Tests (Python) (3.12) (push) Has been cancelled
Tests / Frontend Tests (JS) (push) Has been cancelled
Tests / Integration Tests (push) Has been cancelled
Tests / All Tests Passed (push) Has been cancelled

This commit is contained in:
2026-03-03 08:29:52 -05:00
parent 21d99a0f48
commit 88742892d0
18 changed files with 3016 additions and 9085 deletions
+17 -24
View File
@@ -12,6 +12,7 @@ from time import perf_counter
from typing import Any, Dict, List, Optional
import yaml
from cachetools import TTLCache
from app.core.config import settings
from app.schemas.host_api import AnsibleInventoryHost
@@ -28,27 +29,23 @@ class AnsibleService:
self.ssh_key_path = ssh_key_path or settings.ssh_key_path
self.ssh_user = ssh_user or settings.ssh_user
# Cache
self._inventory_cache: Optional[Dict] = None
self._inventory_cache_time: float = 0
self._playbooks_cache: Optional[List[PlaybookInfo]] = None
self._playbooks_cache_time: float = 0
self._cache_ttl = settings.inventory_cache_ttl
# Cache with automatic TTL eviction (replaces hand-rolled cache)
cache_ttl = settings.inventory_cache_ttl
self._inventory_cache: TTLCache = TTLCache(maxsize=16, ttl=cache_ttl)
self._playbooks_cache: TTLCache = TTLCache(maxsize=16, ttl=cache_ttl)
def invalidate_cache(self):
"""Invalide les caches."""
self._inventory_cache = None
self._playbooks_cache = None
self._inventory_cache.clear()
self._playbooks_cache.clear()
# ===== PLAYBOOKS =====
def get_playbooks(self) -> List[Dict[str, Any]]:
"""Récupère la liste des playbooks disponibles."""
import time
current_time = time.time()
if self._playbooks_cache and (current_time - self._playbooks_cache_time) < self._cache_ttl:
return self._playbooks_cache
cache_key = "all"
if cache_key in self._playbooks_cache:
return self._playbooks_cache[cache_key]
playbooks = []
@@ -78,8 +75,7 @@ class AnsibleService:
if pb:
playbooks.append(pb)
self._playbooks_cache = playbooks
self._playbooks_cache_time = current_time
self._playbooks_cache[cache_key] = playbooks
return playbooks
def _parse_playbook_file(self, file_path: Path, category: str, subcategory: str) -> Optional[Dict[str, Any]]:
@@ -179,11 +175,9 @@ class AnsibleService:
def load_inventory(self) -> Dict:
"""Charge l'inventaire Ansible depuis le fichier YAML."""
import time
current_time = time.time()
if self._inventory_cache and (current_time - self._inventory_cache_time) < self._cache_ttl:
return self._inventory_cache
cache_key = "inventory"
if cache_key in self._inventory_cache:
return self._inventory_cache[cache_key]
if not self.inventory_path.exists():
return {}
@@ -191,8 +185,7 @@ class AnsibleService:
try:
with open(self.inventory_path, 'r', encoding='utf-8') as f:
inventory = yaml.safe_load(f) or {}
self._inventory_cache = inventory
self._inventory_cache_time = current_time
self._inventory_cache[cache_key] = inventory
return inventory
except Exception:
return {}
@@ -204,8 +197,8 @@ class AnsibleService:
with open(self.inventory_path, 'w', encoding='utf-8') as f:
yaml.dump(inventory, f, default_flow_style=False, allow_unicode=True)
# Invalider le cache
self._inventory_cache = None
# Invalider le cache inventaire
self._inventory_cache.clear()
def get_hosts_from_inventory(self, group_filter: str = None) -> List[AnsibleInventoryHost]:
"""Récupère les hôtes depuis l'inventaire Ansible."""
+7 -6
View File
@@ -11,15 +11,16 @@ from datetime import datetime, timedelta, timezone
from typing import Optional
import bcrypt
from jose import JWTError, jwt
import jwt
from app.core.config import settings
from app.models.user import User
from app.schemas.auth import TokenData
# Configuration from environment variables
SECRET_KEY = os.environ.get("JWT_SECRET_KEY", "homelab-secret-key-change-in-production")
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = int(os.environ.get("JWT_EXPIRE_MINUTES", "1440")) # 24 hours default
# Configuration from centralized settings (single source of truth)
SECRET_KEY = settings.jwt_secret_key
ALGORITHM = settings.jwt_algorithm
ACCESS_TOKEN_EXPIRE_MINUTES = settings.jwt_expire_minutes
class AuthService:
@@ -83,7 +84,7 @@ class AuthService:
return None
return TokenData(username=username, user_id=user_id, role=role)
except JWTError:
except (jwt.PyJWTError, jwt.ExpiredSignatureError, jwt.DecodeError):
return None
@staticmethod