ai-agent/tests/security/test_web_interface_security.py

141 lines
No EOL
5.2 KiB
Python

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()