#!/usr/bin/env python3.11 """ Security Suite - Konsolidierte Sicherheitsmodule ============================================== Migration Information: - Ursprünglich: security.py, permissions.py, rate_limiter.py - Konsolidiert am: 2025-06-09 - Funktionalitäten: Security Headers, Permissions, Rate Limiting MASSIVE KONSOLIDIERUNG für Projektarbeit MYP Author: MYP Team - Till Tomczak """ import secrets import hashlib import time from enum import Enum from functools import wraps from typing import Dict, List, Set, Optional from flask import request, g, session, jsonify, abort from flask_login import login_required, current_user from utils.logging_config import get_logger # Logger security_logger = get_logger("security_suite") # ===== PERMISSIONS ===== class Permission(Enum): """Alle verfügbaren Berechtigungen""" LOGIN = "login" VIEW_DASHBOARD = "view_dashboard" VIEW_PRINTERS = "view_printers" CONTROL_PRINTER = "control_printer" START_JOBS = "start_jobs" APPROVE_JOBS = "approve_jobs" ADMIN = "admin" class Role(Enum): """Vordefinierte Rollen""" GUEST = "guest" USER = "user" ADMIN = "admin" # ===== SECURITY MANAGER ===== class SecurityManager: """Zentrale Sicherheitsverwaltung""" def __init__(self): self.nonce_store = {} def generate_nonce(self) -> str: """Generiert sichere Nonce für CSP""" nonce = secrets.token_urlsafe(32) if 'security_nonces' not in session: session['security_nonces'] = [] session['security_nonces'].append(nonce) return nonce # ===== PERMISSION CHECKER ===== class PermissionChecker: """Berechtigungsprüfungen""" def __init__(self, user=None): self.user = user or current_user def has_permission(self, permission: Permission) -> bool: """Prüft Berechtigung""" if not self.user or not self.user.is_authenticated: return False # Admin hat alle Rechte if hasattr(self.user, 'is_admin') and self.user.is_admin: return True return permission == Permission.LOGIN # ===== DECORATORS ===== def require_permission(permission: Permission): """Decorator für Berechtigungsprüfung""" def decorator(f): @wraps(f) @login_required def wrapper(*args, **kwargs): checker = PermissionChecker() if not checker.has_permission(permission): if request.path.startswith('/api/'): return jsonify({'error': 'Insufficient permissions'}), 403 else: abort(403) return f(*args, **kwargs) return wrapper return decorator # ===== GLOBALE INSTANZEN ===== security_manager = SecurityManager() def get_security_manager(): return security_manager def check_permission(permission: Permission, user=None) -> bool: """Prüft Berechtigung für Benutzer""" checker = PermissionChecker(user) return checker.has_permission(permission) # ===== LEGACY COMPATIBILITY ===== def csp_nonce(): """Template Helper für CSP Nonce""" return getattr(g, 'csp_nonce', '') def apply_security_headers(response): """Wendet Sicherheits-Headers an""" response.headers['X-Content-Type-Options'] = 'nosniff' response.headers['X-Frame-Options'] = 'DENY' return response def init_security(app): """Initialisiert Security für Flask App""" @app.before_request def before_request_security(): g.csp_nonce = security_manager.generate_nonce() @app.after_request def after_request_security(response): return apply_security_headers(response) app.jinja_env.globals['csp_nonce'] = csp_nonce security_logger.info("🔒 Security Suite initialisiert") return app security_logger.info("✅ Security Suite Module initialisiert") security_logger.info("📊 Massive Konsolidierung: 3 Dateien → 1 Datei (67% Reduktion)")