feat: Implement service-to-service authentication, centralize environment configuration, and harden Docker security.

This commit is contained in:
2026-01-29 19:41:59 -03:00
parent 5d85dc0714
commit 5075a2440d
6 changed files with 169 additions and 12 deletions

View File

@@ -20,6 +20,7 @@ MODEL_PATH = os.environ.get('MODEL_PATH', 'best.pt')
DATASET_DIR = os.environ.get('DATASET_DIR', '/app/dataset')
DATASET_COOLDOWN = int(os.environ.get('DATASET_COOLDOWN', 60))
OCR_WORKERS = int(os.environ.get('OCR_WORKERS', 2)) # Número de workers OCR
SERVICE_API_KEY = os.environ.get('SERVICE_API_KEY', '') # For backend auth
app = Flask(__name__)
CORS(app)
@@ -129,7 +130,10 @@ def send_plate(plate_number):
"""Envía la patente detectada al backend"""
try:
url = f"{BACKEND_URL}/api/detect"
requests.post(url, json={'plate_number': plate_number}, timeout=3)
headers = {}
if SERVICE_API_KEY:
headers['X-Service-Key'] = SERVICE_API_KEY
requests.post(url, json={'plate_number': plate_number}, headers=headers, timeout=3)
print(f"✓ Plate sent: {plate_number}")
with metrics_lock:
@@ -348,7 +352,24 @@ def dataset_list():
def dataset_image(filename):
return send_from_directory(DATASET_DIR, filename)
# SECURITY: Auth decorator for destructive operations
from functools import wraps
def require_auth(f):
@wraps(f)
def decorated(*args, **kwargs):
if not SERVICE_API_KEY:
# No key configured = dev mode, allow but warn
print("⚠️ SERVICE_API_KEY not set - dataset DELETE unprotected!")
return f(*args, **kwargs)
provided_key = request.headers.get('X-Service-Key', '')
if provided_key != SERVICE_API_KEY:
return {"error": "Unauthorized"}, 401
return f(*args, **kwargs)
return decorated
@app.route("/dataset/images/<filename>", methods=['DELETE'])
@require_auth
def delete_dataset_image(filename):
"""Elimina una imagen del dataset"""
try: