Commits (2)
# 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
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/<string:hash_value>", 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)
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
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