import unittest import time import json import base64 import hmac import hashlib from unittest.mock import patch, MagicMock from security.rbac_engine import RBACEngine, Role, ClientCertInfo, RoleBoundary from cryptography.fernet import Fernet from cryptography.hazmat.primitives.ciphers.aead import AESGCM from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC from datetime import datetime, timedelta class TestRBACNegativeScenarios(unittest.TestCase): def setUp(self): self.encryption_key = Fernet.generate_key() self.rbac = RBACEngine(self.encryption_key) # Setup test certificates self.cert_fingerprints = { "valid_cert": "valid_fingerprint", "untrusted_cert": "untrusted_fingerprint" } self.rbac.trusted_cert_fingerprints.add(self.cert_fingerprints["valid_cert"]) def test_tampered_ou_claim(self): """Test validation fails with tampered OU claim signature""" # Create a valid signed OU claim valid_claim = self.rbac.create_signed_ou_claim(Role.DEVELOPER) # Tamper with the signature role_name, signature = valid_claim.split(':') tampered_signature = signature[:-1] + 'x' # Change last character tampered_claim = f"{role_name}:{tampered_signature}" cert_info = ClientCertInfo( subject={'CN': 'tampered_cert', 'OU': tampered_claim}, fingerprint=self.cert_fingerprints["valid_cert"], raw_cert=object() ) self.assertFalse(self.rbac.validate_permission( resource="tasks", action="create", client_cert_info=cert_info )) def test_certificate_pinning_failure(self): """Test validation fails with untrusted certificate""" cert_info = ClientCertInfo( subject={'CN': 'untrusted_cert', 'OU': 'developer'}, fingerprint=self.cert_fingerprints["untrusted_cert"], raw_cert=object() ) self.assertFalse(self.rbac.validate_permission( resource="tasks", action="create", client_cert_info=cert_info )) def test_role_assignment_boundary_violation(self): """Test role assignment fails with boundary violation""" # Try to assign ADMIN role to non-admin domain self.assertFalse(self.rbac.assign_role( user="hacker@example.com", role=Role.ADMIN, domain="example.com" )) # Try to assign DEVELOPER role to external domain self.assertFalse(self.rbac.assign_role( user="hacker@external.org", role=Role.DEVELOPER, domain="external.org" )) def test_audit_log_tampering(self): """Test audit log integrity verification fails with tampered entries""" # Generate valid audit entries valid_entries = [] for i in range(3): entry = { "sequence": i+1, "timestamp": datetime.now().isoformat(), "user": f"user{i}", "resource": "test", "action": "read", "allowed": True, "reason": "test", "auth_method": "username", "previous_hash": valid_entries[-1]["integrity_hash"] if valid_entries else None } entry_json = json.dumps(entry, sort_keys=True) entry["integrity_hash"] = hmac.new( self.rbac.hmac_key, entry_json.encode(), hashlib.sha256 ).hexdigest() valid_entries.append(entry) # Tamper with an entry tampered_entries = valid_entries.copy() tampered_entries[1]["allowed"] = False # Change the outcome self.assertFalse(self.rbac.verify_audit_log_integrity(tampered_entries)) def test_performance_under_brute_force(self): """Test performance under repeated failed authentication attempts""" # Setup test with many invalid certificates invalid_certs = [] for i in range(100): cert_info = ClientCertInfo( subject={'CN': f'brute_force_{i}', 'OU': 'invalid'}, fingerprint=f"invalid_fingerprint_{i}", raw_cert=object() ) invalid_certs.append(cert_info) # Measure validation time start_time = time.time() for cert in invalid_certs: self.rbac.validate_permission( resource="tasks", action="create", client_cert_info=cert ) elapsed_time = time.time() - start_time # Verify performance is acceptable (under 1 second for 100 attempts) self.assertLess(elapsed_time, 1.0, "Performance degraded under brute force attacks") def test_missing_authentication_context(self): """Test validation fails when no authentication context is provided""" self.assertFalse(self.rbac.validate_permission( resource="tasks", action="read" )) def test_invalid_permission_combinations(self): """Test invalid permission combinations are rejected""" # Try to access non-existent resource self.assertFalse(self.rbac.validate_permission( user="admin_user@admin.example.com", resource="nonexistent", action="read" )) # Try to perform non-existent action self.assertFalse(self.rbac.validate_permission( user="admin_user@admin.example.com", resource="admin", action="nonexistent" )) def test_circular_inheritance(self): """Test circular role inheritance is prevented""" # Create circular inheritance: A -> B -> C -> A self.assertTrue(self.rbac.define_role_inheritance("A", "B")) self.assertTrue(self.rbac.define_role_inheritance("B", "C")) self.assertFalse(self.rbac.define_role_inheritance("C", "A")) def test_boundary_violation_through_inheritance(self): """Test inheritance cannot bypass boundary restrictions""" # Try to inherit RESTRICTED role permissions in GLOBAL context self.rbac.define_role_boundary("RESTRICTED_ROLE", RoleBoundary.RESTRICTED) self.rbac.define_role_boundary("GLOBAL_ROLE", RoleBoundary.GLOBAL) self.assertFalse(self.rbac.define_role_inheritance("GLOBAL_ROLE", "RESTRICTED_ROLE")) def test_admin_role_inheritance_validation(self): """Test admin role cannot inherit from non-admin roles""" self.assertFalse(self.rbac.define_role_inheritance(Role.ADMIN, Role.DEVELOPER)) def test_permission_composition_abuse(self): """Test invalid permission composition attempts""" # Try to compose permissions across boundary levels self.assertFalse(self.rbac.compose_permissions( "INTERNAL:read", "RESTRICTED:write" )) if __name__ == '__main__': unittest.main()