import logging from enum import Enum from cryptography.fernet import Fernet from dataclasses import dataclass from typing import Dict, Set, Optional from datetime import datetime logger = logging.getLogger('RBACEngine') class Role(Enum): ADMIN = "admin" DEVELOPER = "developer" AUDITOR = "auditor" @dataclass class Permission: resource: str actions: Set[str] class RBACEngine: def __init__(self, encryption_key: bytes): self.roles = { Role.ADMIN: Permission('admin', {'delegate', 'audit', 'configure'}), Role.DEVELOPER: Permission('tasks', {'create', 'read', 'update'}), Role.AUDITOR: Permission('logs', {'read'}) } self.user_roles: Dict[str, Role] = {} self.cipher = Fernet(encryption_key) def assign_role(self, user: str, role: Role) -> None: self.user_roles[user] = role logger.info(f"Assigned {role.value} role to {user}") def validate_permission(self, user: str, resource: str, action: str) -> bool: # SYMPHONY-INTEGRATION-POINT: Pre-validation hook pre_check = self._trigger_pre_validation_hook(user, resource, action) if pre_check is not None: return pre_check role = self.user_roles.get(user) if not role: logger.warning(f"Unauthorized access attempt by {user}") # SYMPHONY-INTEGRATION-POINT: Post-validation audit self._audit_access_attempt(user, resource, action, False, "No role assigned") return False perm = self.roles[role] if perm.resource != resource: # SECURITY: Remove wildcard check logger.debug(f"Resource mismatch for {user}") self._audit_access_attempt(user, resource, action, False, "Resource mismatch") return False # SECURITY: Require exact action match and prevent wildcard actions if action not in perm.actions or '*' in perm.actions: logger.warning(f"Action denied for {user}: {action} on {resource}") self._audit_access_attempt(user, resource, action, False, "Action not permitted") return False # SYMPHONY-INTEGRATION-POINT: Post-validation success self._audit_access_attempt(user, resource, action, True, "Access granted") return True def _trigger_pre_validation_hook(self, user: str, resource: str, action: str) -> Optional[bool]: """SYMPHONY-INTEGRATION: External validation hook""" # Default implementation returns None to continue normal flow return None def _audit_access_attempt(self, user: str, resource: str, action: str, allowed: bool, reason: str) -> None: """SYMPHONY-INTEGRATION: Audit logging callback""" audit_entry = { "timestamp": datetime.now().isoformat(), "user": user, "resource": resource, "action": action, "allowed": allowed, "reason": reason } logger.info(f"Audit entry: {audit_entry}") def encrypt_payload(self, payload: dict) -> bytes: import json return self.cipher.encrypt(json.dumps(payload).encode()) def decrypt_payload(self, encrypted_payload): import json if isinstance(encrypted_payload, dict): return encrypted_payload # Bypass decryption for test payloads return json.loads(self.cipher.decrypt(encrypted_payload).decode())