144 lines
4.0 KiB
Python
144 lines
4.0 KiB
Python
#!/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)") |