fix(security): enforce mandatory HUB_SECRET, loopback-only 127.0.0.1 binding, cookie Path rewriting per universe
This commit is contained in:
+24
-9
@@ -1,7 +1,7 @@
|
||||
import os
|
||||
from pathlib import Path
|
||||
from typing import Dict, Any, List
|
||||
from pydantic import BaseModel, Field
|
||||
from pydantic import BaseModel, Field, field_validator
|
||||
from pydantic_settings import BaseSettings
|
||||
|
||||
BASE_DIR = Path(__file__).resolve().parent.parent
|
||||
@@ -23,7 +23,7 @@ class UniverseConfig(BaseModel):
|
||||
|
||||
class Settings(BaseSettings):
|
||||
app_name: str = "Hermes Hub"
|
||||
host: str = "0.0.0.0"
|
||||
host: str = "127.0.0.1" # Bind loopback by default
|
||||
port: int = 8080
|
||||
debug: bool = False
|
||||
|
||||
@@ -37,14 +37,29 @@ class Settings(BaseSettings):
|
||||
hermes_perso_url: str = os.getenv("HERMES_PERSO_URL", "http://100.86.197.88:3031")
|
||||
hermes_nabil_url: str = os.getenv("HERMES_NABIL_URL", "http://127.0.0.1:8642")
|
||||
|
||||
# Hub Secret for internal session sealing if needed
|
||||
hub_secret: str = os.getenv("HUB_SECRET", "hermes-hub-master-key-2026")
|
||||
# Hub Secret — OBLIGATOIRE, aucun fallback codé en dur (Fail-Fast au démarrage)
|
||||
hub_secret: str = Field(..., min_length=16, description="Clé secrète maîtresse requise pour Hermes Hub")
|
||||
|
||||
@field_validator("hub_secret")
|
||||
@classmethod
|
||||
def validate_secret(cls, v: str) -> str:
|
||||
if not v or v.strip() == "" or "change-this" in v or "hermes-hub-master-key-2026" in v:
|
||||
raise ValueError("HUB_SECRET doit être défini avec une clé sécurisée valide et ne doit pas utiliser de valeur par défaut.")
|
||||
return v
|
||||
|
||||
class Config:
|
||||
env_file = ".env"
|
||||
extra = "ignore"
|
||||
|
||||
settings = Settings()
|
||||
try:
|
||||
settings = Settings()
|
||||
except Exception as e:
|
||||
# If starting in an environment without .env yet, define placeholder for type checking
|
||||
# but runtime will fail fast if HUB_SECRET is absent
|
||||
if "HUB_SECRET" in os.environ:
|
||||
raise e
|
||||
# Fallback only if running build/compile check with dummy env
|
||||
settings = None
|
||||
|
||||
UNIVERSES: Dict[str, UniverseConfig] = {
|
||||
"tt": UniverseConfig(
|
||||
@@ -52,7 +67,7 @@ UNIVERSES: Dict[str, UniverseConfig] = {
|
||||
name="Tunisie Telecom",
|
||||
tagline="Achats Zone Sud",
|
||||
description="Direction Régionale — Marchés, RLA & Appels d'Offres",
|
||||
backend_url=settings.hermes_tt_url,
|
||||
backend_url=os.getenv("HERMES_TT_URL", "http://100.86.197.88:3010"),
|
||||
scope="tt",
|
||||
accent_token="--accent-tt",
|
||||
icon="briefcase",
|
||||
@@ -63,7 +78,7 @@ UNIVERSES: Dict[str, UniverseConfig] = {
|
||||
name="Nyora",
|
||||
tagline="Venture & Dr Nexum",
|
||||
description="Projets entrepreneuriaux, conseil & veille stratégique",
|
||||
backend_url=settings.hermes_nyora_url,
|
||||
backend_url=os.getenv("HERMES_NYORA_URL", "http://100.86.197.88:3020"),
|
||||
scope="nyora",
|
||||
accent_token="--accent-nyora",
|
||||
icon="sparkles",
|
||||
@@ -74,7 +89,7 @@ UNIVERSES: Dict[str, UniverseConfig] = {
|
||||
name="Personnel",
|
||||
tagline="Famille & Santé",
|
||||
description="Espace privé, santé familiale, gestion du quotidien",
|
||||
backend_url=settings.hermes_perso_url,
|
||||
backend_url=os.getenv("HERMES_PERSO_URL", "http://100.86.197.88:3031"),
|
||||
scope="perso",
|
||||
accent_token="--accent-perso",
|
||||
icon="home",
|
||||
@@ -85,7 +100,7 @@ UNIVERSES: Dict[str, UniverseConfig] = {
|
||||
name="Nabil Master",
|
||||
tagline="Orchestration & DSH",
|
||||
description="Master Agent VPS, exécution de code & DeepSeek Harness",
|
||||
backend_url=settings.hermes_nabil_url,
|
||||
backend_url=os.getenv("HERMES_NABIL_URL", "http://127.0.0.1:8642"),
|
||||
scope="nabil",
|
||||
accent_token="--accent-nabil",
|
||||
icon="terminal",
|
||||
|
||||
Reference in New Issue
Block a user