Public Access
feat: Préparation au déploiement Docker, sécurisation du README et ajout du module de facturation
This commit is contained in:
1 parent
317ecddc56
commit
37ee5c6234
5 files changed
+163
-12
No files matched your search
@@ -0,0 +1,47 @@
|
||||
import os
|
||||
import bcrypt
|
||||
from cryptography.fernet import Fernet
|
||||
from modules.logger import log_event
|
||||
|
||||
# 1. GÉNÉRATION DE LA CLÉ DE CRYPTAGE (À ne faire qu'une fois)
|
||||
def generer_cle_secrete():
|
||||
"""Génère une clé Fernet unique. À sauvegarder dans le .env"""
|
||||
cle = Fernet.generate_key()
|
||||
print("\n" + "="*60)
|
||||
print("⚠️ CLÉ DE CRYPTAGE GÉNÉRÉE (À CONSERVER PRÉCIEUSEMENT) ⚠️")
|
||||
print(f"AETHAS_ENCRYPTION_KEY={cle.decode('utf-8')}")
|
||||
print("Copiez cette ligne dans votre fichier .env")
|
||||
print("="*60 + "\n")
|
||||
return cle
|
||||
|
||||
def obtenir_fernet():
|
||||
cle = os.getenv("AETHAS_ENCRYPTION_KEY")
|
||||
if not cle:
|
||||
log_event("CRITICAL", "AUTH", "Clé de cryptage manquante !")
|
||||
raise Exception("AETHAS_ENCRYPTION_KEY introuvable dans l'environnement.")
|
||||
return Fernet(cle.encode('utf-8'))
|
||||
|
||||
# 2. CRYPTAGE DES DONNÉES SENSIBLES (Clés API des utilisateurs, CB, etc.)
|
||||
def crypter_donnee(donnee_claire):
|
||||
f = obtenir_fernet()
|
||||
return f.encrypt(donnee_claire.encode('utf-8')).decode('utf-8')
|
||||
|
||||
def decrypter_donnee(donnee_cryptee):
|
||||
f = obtenir_fernet()
|
||||
return f.decrypt(donnee_cryptee.encode('utf-8')).decode('utf-8')
|
||||
|
||||
# 3. GESTION DES MOTS DE PASSE (Hashing irréversible)
|
||||
def hasher_mot_de_passe(mot_de_passe):
|
||||
"""Hash le mot de passe avec un 'salt' unique pour la base de données."""
|
||||
return bcrypt.hashpw(mot_de_passe.encode('utf-8'), bcrypt.gensalt()).decode('utf-8')
|
||||
|
||||
def verifier_mot_de_passe(mot_de_passe_clair, hash_enregistre):
|
||||
return bcrypt.checkpw(mot_de_passe_clair.encode('utf-8'), hash_enregistre.encode('utf-8'))
|
||||
|
||||
# --- CRÉATION DE VOTRE COMPTE ADMINISTRATEUR PAR DÉFAUT ---
|
||||
IDENTIFIANTS_ADMIN = {
|
||||
"email": "admin@mail.aethas38.duckdns.org",
|
||||
# Mot de passe par défaut : Xavier2026! (Il est hashé ici pour la sécurité du code)
|
||||
"mot_de_passe_hash": "$2b$12$R.K19pS8M5/xVd2o.3nSZeZ8GzH6J9gR/vY9x6g3Zp2vJq4vX2J0e",
|
||||
"role": "Dieu tout puissant"
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
import json
|
||||
import os
|
||||
import time
|
||||
import requests
|
||||
from datetime import datetime
|
||||
from modules.logger import log_event
|
||||
|
||||
LOG_FILE = "aethas_ip_logs.json"
|
||||
|
||||
def verifier_et_bloquer_vpn(ip_address):
|
||||
"""
|
||||
Vérifie si une IP appartient à un VPN, un Proxy ou un Datacenter.
|
||||
Utilise l'API publique gratuite blackbox.ipinfo.app (Renvoie 'Y' si VPN, 'N' si clean).
|
||||
"""
|
||||
# On ne bloque jamais les requêtes locales du serveur (localhost)
|
||||
if ip_address in ["127.0.0.1", "localhost", "::1"]:
|
||||
return False
|
||||
|
||||
try:
|
||||
# Requête ultra-légère, timeout court pour ne pas ralentir le site
|
||||
reponse = requests.get(f"https://blackbox.ipinfo.app/lookup/{ip_address}", timeout=3)
|
||||
if reponse.text.strip() == "Y":
|
||||
log_event("WARNING", "SECURITY", f"Tentative de connexion VPN bloquée pour l'IP : {ip_address}")
|
||||
return True # True = C'est un VPN, il faut bloquer
|
||||
except requests.RequestException as e:
|
||||
# En cas de panne de l'API de vérification, on laisse passer pour ne pas bloquer les utilisateurs légitimes
|
||||
log_event("ERROR", "SECURITY", f"Erreur lors de la vérification VPN pour {ip_address}: {e}")
|
||||
|
||||
return False
|
||||
|
||||
def journaliser_ip(ip_address, action="Connexion"):
|
||||
"""
|
||||
Enregistre l'IP pour la conformité légale (RGPD).
|
||||
Purge automatique des logs vieux de plus de 365 jours.
|
||||
"""
|
||||
logs = []
|
||||
|
||||
# 1. Chargement de l'historique existant
|
||||
if os.path.exists(LOG_FILE):
|
||||
with open(LOG_FILE, 'r', encoding='utf-8') as f:
|
||||
try:
|
||||
logs = json.load(f)
|
||||
except json.JSONDecodeError:
|
||||
logs = []
|
||||
|
||||
# 2. Nettoyage RGPD : on supprime les logs de plus d'un an (365 jours = 31 536 000 secondes)
|
||||
un_an_en_arriere = time.time() - 31536000
|
||||
logs = [log for log in logs if log.get("timestamp", 0) > un_an_en_arriere]
|
||||
|
||||
# 3. Ajout de la nouvelle entrée
|
||||
logs.append({
|
||||
"ip": ip_address,
|
||||
"action": action,
|
||||
"date": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
|
||||
"timestamp": time.time()
|
||||
})
|
||||
|
||||
# 4. Sauvegarde
|
||||
with open(LOG_FILE, 'w', encoding='utf-8') as f:
|
||||
json.dump(logs, f, indent=4)
|
||||
|
||||
log_event("INFO", "SECURITY", f"IP {ip_address} journalisée pour raison légale ({action}).")
|
||||
Reference in new issue
Block a user