import unittest import ssl from web_interface import app from security.audit import SecureAudit from security.rbac_engine import RBACEngine class TestWebInterfaceSecurity(unittest.TestCase): def setUp(self): self.client = app.test_client() self.audit = SecureAudit(self.rbac) self.rbac = RBACEngine() def test_tls_configuration(self): context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_3) self.assertIn('AES256-GCM', context.get_ciphers()[0]['name']) def test_security_headers(self): response = self.client.get('/permissions/validate') self.assertEqual(response.headers['X-Frame-Options'], 'SAMEORIGIN') self.assertEqual(response.headers['X-Content-Type-Options'], 'nosniff') def test_rate_limiting(self): for _ in range(10): response = self.client.post('/tasks') self.assertEqual(response.status_code, 200) response = self.client.post('/tasks') self.assertEqual(response.status_code, 429) def test_audit_logging(self): with self.assertLogs('audit', level='INFO') as cm: self.client.post('/tasks') self.assertIn('task_add', cm.output[0]) def test_rbac_integration(self): response = self.client.post('/tasks') self.assertIn(response.status_code, [401, 403]) def test_batch_integrity_verification(self): """Verify cryptographic integrity of batched entries""" # Generate test operations test_ops = [ {'operation': 'task_add', 'data': 'test1', 'user': 'user1', 'status': 'completed'}, {'operation': 'task_add', 'data': 'test2', 'user': 'user2', 'status': 'failed'} ] # Process batch with self.assertLogs('audit', level='INFO') as cm: for op in test_ops: self.audit.log_operation(**op) # Verify integrity logs = [record.getMessage() for record in cm.records] self.assertEqual(len(logs), 2) # Should be 2 entries self.assertIn('integrity_hash=', logs[0]) # First entry has hash self.assertIn('prev_hash=', logs[1]) # Second entry references first def test_timer_flush_security(self): """Verify timer-based flush maintains security properties""" # Setup test_op = {'operation': 'task_add', 'data': 'test', 'user': 'user1', 'status': 'completed'} # Log operation and force timer flush with self.assertLogs('audit', level='INFO') as cm: self.audit.log_operation(**test_op) self.audit._flush_batch() # Force flush # Verify self.assertIn('Batch flushed', cm.output[0]) self.assertIn('integrity_hash=', cm.output[0]) def test_size_flush_security(self): """Verify size-based flush maintains security properties""" # Setup test_ops = [ {'operation': 'task_add', 'data': f'test{i}', 'user': f'user{i}', 'status': 'completed'} for i in range(10) # Batch size limit ] # Log operations (should trigger size-based flush) with self.assertLogs('audit', level='INFO') as cm: for op in test_ops: self.audit.log_operation(**op) # Verify flush occurred and has integrity self.assertIn('Batch size limit reached', cm.output[-1]) self.assertIn('integrity_hash=', cm.output[-1]) def test_rbac_batch_notifications(self): """Verify RBAC notifications for batched operations""" # Setup test user with permissions self.rbac.grant_permission('user1', 'batch_operations') # Test operation test_op = {'operation': 'task_add', 'data': 'test', 'user': 'user1', 'status': 'completed'} # Log operation and verify notification with self.assertLogs('rbac', level='INFO') as cm: self.audit.log_operation(**test_op) self.audit._flush_batch() # Verify notification self.assertIn('Batch operation notification', cm.output[0]) self.assertIn('user1', cm.output[0]) def test_thread_safety(self): """Verify thread-safe operation during concurrent access""" import threading # Shared test data test_ops = [ {'operation': 'task_add', 'data': f'test{i}', 'user': f'user{i}', 'status': 'completed'} for i in range(20) ] results = [] # Worker function def worker(op): try: self.audit.log_operation(**op) results.append(True) except Exception: results.append(False) # Create and start threads threads = [] for op in test_ops: t = threading.Thread(target=worker, args=(op,)) threads.append(t) t.start() # Wait for completion for t in threads: t.join() # Verify all operations succeeded self.assertTrue(all(results)) self.assertEqual(len(results), len(test_ops)) if __name__ == '__main__': unittest.main()