From ee20dad939429cf3a8f477ce8881434f1ca3282e Mon Sep 17 00:00:00 2001 From: Radia Fali Date: Mon, 10 Mar 2025 23:11:40 +0100 Subject: [PATCH] Ajout Backend --- backend/Dockerfile | 23 +++++++ backend/main.py | 143 +++++++++++++++++++++++++++++++++++++++ backend/requirements.txt | 12 ++++ backend/stack.yml | 46 +++++++++++++ 4 files changed, 224 insertions(+) create mode 100644 backend/Dockerfile create mode 100644 backend/main.py create mode 100644 backend/requirements.txt create mode 100644 backend/stack.yml diff --git a/backend/Dockerfile b/backend/Dockerfile new file mode 100644 index 0000000..dbee536 --- /dev/null +++ b/backend/Dockerfile @@ -0,0 +1,23 @@ +# Utiliser une image officielle Python comme base +FROM python:3.11 + +# Définir le répertoire de travail dans le conteneur +WORKDIR /app + +# Installer Docker CLI +RUN apt-get update && apt-get install -y docker.io + +# Copier les fichiers nécessaires +COPY requirements.txt . + +# Installer les dépendances +RUN pip install --no-cache-dir -r requirements.txt + +# Copier le reste du code +COPY . . + +# Exposer le port sur lequel Flask écoute +EXPOSE 5000 + +# Commande pour lancer l'application +CMD ["python", "main.py"] \ No newline at end of file diff --git a/backend/main.py b/backend/main.py new file mode 100644 index 0000000..bde3db1 --- /dev/null +++ b/backend/main.py @@ -0,0 +1,143 @@ +import os +import redis +import hashlib +import itertools +from flask import Flask, request, jsonify +from flask_cors import CORS + +app = Flask(__name__) +CORS(app) + +# Configuration de Redis +redis_host = os.getenv("REDIS_HOST", "redis") +redis_port = int(os.getenv("REDIS_PORT", 6379)) +redis_client = redis.StrictRedis(host=redis_host, port=redis_port, db=0, decode_responses=True) + +# Clé pour le compteur de requêtes reçues +REQUEST_RECEIVED_KEY = "request_received_count" + +# Initialisation du compteur si inexistant +if not redis_client.exists(REQUEST_RECEIVED_KEY): + redis_client.set(REQUEST_RECEIVED_KEY, 0) + + +@app.before_request +def count_requests(): + """ + Middleware exécuté avant chaque requête pour incrémenter le compteur global de requêtes reçues. + """ + redis_client.incr(REQUEST_RECEIVED_KEY) + + +@app.route("/health", methods=["GET"]) +def health(): + """ Vérifie si l'application fonctionne correctement. """ + return jsonify({"status": "ok"}), 200 + + +@app.route("/bruteforce", methods=["POST"]) +def bruteforce(): + """ + Endpoint pour bruteforcer un hash MD5. + """ + data = request.json + if not data or "hash" not in data: + return jsonify({ + "status": "fail", + "data": None, + "errors": {"message": "Invalid payload. Please provide a valid hash."} + }), 400 + + target_hash = data["hash"] + + # Vérifier si le hash existe déjà dans Redis + if redis_client.exists(target_hash): + original = redis_client.get(target_hash) + return jsonify({ + "status": "success", + "data": {"hash": target_hash, "original": original}, + "errors": None + }), 200 + + # Logique de brute-force + charset = "abcdefghijklmnopqrstuvwxyz0123456789" + for length in range(1, 8): + for guess in itertools.product(charset, repeat=length): + guess_str = ''.join(guess) + if hashlib.md5(guess_str.encode()).hexdigest() == target_hash: + redis_client.set(target_hash, guess_str) + return jsonify({ + "status": "success", + "data": {"hash": target_hash, "original": guess_str}, + "errors": None + }), 200 + + return jsonify({ + "status": "fail", + "data": None, + "errors": {"message": "No match found."} + }), 404 + + +@app.route("/resolved", methods=["GET"]) +def get_resolved_hashes(): + """ + Endpoint pour récupérer tous les hash résolus. + """ + keys = redis_client.keys() + resolved_hashes = {key: redis_client.get(key) for key in keys if key != REQUEST_RECEIVED_KEY} + return jsonify({ + "status": "success", + "data": resolved_hashes, + "errors": None + }), 200 + + +@app.route("/resolved/", methods=["GET"]) +def get_resolved_hash(hash_value): + """ + Endpoint pour récupérer un hash spécifique. + """ + if redis_client.exists(hash_value): + original = redis_client.get(hash_value) + return jsonify({ + "status": "success", + "data": {"hash": hash_value, "original": original}, + "errors": None + }), 200 + else: + return jsonify({ + "status": "fail", + "data": None, + "errors": {"message": f"No resolved entry found for hash: {hash_value}"} + }), 404 + + +@app.route("/request_count", methods=["GET"]) +def get_request_count(): + """ + Endpoint pour récupérer le nombre total de requêtes reçues. + """ + count = redis_client.get(REQUEST_RECEIVED_KEY) + return jsonify({ + "status": "success", + "data": {"request_received_count": int(count) if count else 0}, + "errors": None + }), 200 + + +@app.route("/clear_cache", methods=["DELETE"]) +def clear_cache(): + """ + Endpoint pour effacer toutes les entrées stockées dans Redis (sauf le compteur de requêtes). + """ + keys = redis_client.keys() + for key in keys: + if key != REQUEST_RECEIVED_KEY: + redis_client.delete(key) + + return jsonify({"status": "success", "message": "Cache cleared."}), 200 + + +if __name__ == "__main__": + app.run(host="0.0.0.0", port=5000) diff --git a/backend/requirements.txt b/backend/requirements.txt new file mode 100644 index 0000000..ecc8874 --- /dev/null +++ b/backend/requirements.txt @@ -0,0 +1,12 @@ +blinker==1.8.2 +click==8.1.8 +colorama==0.4.6 +flask==3.0.3 +importlib-metadata==8.5.0 +itsdangerous==2.2.0 +jinja2==3.1.5 +MarkupSafe==2.1.5 +werkzeug==3.0.6 +zipp==3.20.2 +redis==5.2.1 +flask-cors==4.0.0 \ No newline at end of file diff --git a/backend/stack.yml b/backend/stack.yml new file mode 100644 index 0000000..3768f10 --- /dev/null +++ b/backend/stack.yml @@ -0,0 +1,46 @@ +version: "3.8" + +services: + redis: + image: redis:alpine + networks: + - app_network + healthcheck: + test: ["CMD", "redis-cli", "ping"] + interval: 10s + timeout: 5s + retries: 3 + deploy: + restart_policy: + condition: any + + backend: + image: md5_backend:latest + deploy: + replicas: 1 + restart_policy: + condition: any + mode: replicated + placement: + constraints: [node.role == manager] + ports: + - target: 5000 + published: 5000 + protocol: tcp + mode: host + networks: + - app_network + environment: + - REDIS_HOST=redis + - REDIS_PORT=6379 + depends_on: + - redis + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:5000/health"] + interval: 10s + timeout: 5s + retries: 3 + +networks: + app_network: + driver: overlay -- GitLab