389 lines
16 KiB
Python
389 lines
16 KiB
Python
"""
|
|
Enhanced audit logging models for P2 security features
|
|
"""
|
|
from datetime import datetime, timezone
|
|
from typing import Optional, Dict, Any
|
|
from enum import Enum
|
|
import json
|
|
|
|
from sqlalchemy import Column, Integer, String, DateTime, Boolean, ForeignKey, Text, Index
|
|
from sqlalchemy.orm import relationship
|
|
from sqlalchemy.dialects.postgresql import JSONB
|
|
|
|
from app.models.base import BaseModel
|
|
|
|
|
|
class SecurityEventType(str, Enum):
|
|
"""Security event types for classification"""
|
|
# Authentication events
|
|
LOGIN_SUCCESS = "login_success"
|
|
LOGIN_FAILURE = "login_failure"
|
|
LOGOUT = "logout"
|
|
SESSION_EXPIRED = "session_expired"
|
|
PASSWORD_CHANGE = "password_change"
|
|
ACCOUNT_LOCKED = "account_locked"
|
|
|
|
# Authorization events
|
|
ACCESS_DENIED = "access_denied"
|
|
PRIVILEGE_ESCALATION = "privilege_escalation"
|
|
UNAUTHORIZED_ACCESS = "unauthorized_access"
|
|
|
|
# Data access events
|
|
DATA_READ = "data_read"
|
|
DATA_WRITE = "data_write"
|
|
DATA_DELETE = "data_delete"
|
|
DATA_EXPORT = "data_export"
|
|
BULK_OPERATION = "bulk_operation"
|
|
|
|
# System events
|
|
CONFIGURATION_CHANGE = "configuration_change"
|
|
USER_CREATION = "user_creation"
|
|
USER_MODIFICATION = "user_modification"
|
|
USER_DELETION = "user_deletion"
|
|
|
|
# Security events
|
|
SUSPICIOUS_ACTIVITY = "suspicious_activity"
|
|
ATTACK_DETECTED = "attack_detected"
|
|
SECURITY_VIOLATION = "security_violation"
|
|
IP_BLOCKED = "ip_blocked"
|
|
|
|
# File events
|
|
FILE_UPLOAD = "file_upload"
|
|
FILE_DOWNLOAD = "file_download"
|
|
FILE_DELETION = "file_deletion"
|
|
FILE_MODIFICATION = "file_modification"
|
|
|
|
# Integration events
|
|
API_ACCESS = "api_access"
|
|
EXTERNAL_SERVICE = "external_service"
|
|
IMPORT_OPERATION = "import_operation"
|
|
|
|
|
|
class SecurityEventSeverity(str, Enum):
|
|
"""Security event severity levels"""
|
|
CRITICAL = "critical"
|
|
HIGH = "high"
|
|
MEDIUM = "medium"
|
|
LOW = "low"
|
|
INFO = "info"
|
|
|
|
|
|
class ComplianceStandard(str, Enum):
|
|
"""Compliance standards for reporting"""
|
|
SOX = "sox" # Sarbanes-Oxley
|
|
HIPAA = "hipaa" # Health Insurance Portability and Accountability Act
|
|
GDPR = "gdpr" # General Data Protection Regulation
|
|
SOC2 = "soc2" # Service Organization Control 2
|
|
ISO27001 = "iso27001" # Information Security Management
|
|
NIST = "nist" # National Institute of Standards and Technology
|
|
|
|
|
|
class EnhancedAuditLog(BaseModel):
|
|
"""
|
|
Enhanced audit logging for comprehensive security monitoring
|
|
"""
|
|
__tablename__ = "enhanced_audit_logs"
|
|
|
|
id = Column(Integer, primary_key=True, autoincrement=True, index=True)
|
|
|
|
# Event identification
|
|
event_id = Column(String(64), nullable=False, unique=True, index=True)
|
|
event_type = Column(String(50), nullable=False, index=True)
|
|
event_category = Column(String(30), nullable=False, index=True) # security, audit, compliance, system
|
|
severity = Column(String(20), nullable=False, index=True)
|
|
|
|
# Event details
|
|
title = Column(String(255), nullable=False)
|
|
description = Column(Text, nullable=False)
|
|
outcome = Column(String(20), nullable=False, index=True) # success, failure, error, blocked
|
|
|
|
# User and session context
|
|
user_id = Column(Integer, ForeignKey("users.id"), nullable=True, index=True)
|
|
session_id = Column(String(128), nullable=True, index=True)
|
|
impersonated_user_id = Column(Integer, ForeignKey("users.id"), nullable=True)
|
|
|
|
# Network context
|
|
source_ip = Column(String(45), nullable=True, index=True)
|
|
user_agent = Column(Text, nullable=True)
|
|
request_id = Column(String(64), nullable=True, index=True)
|
|
|
|
# Geographic context
|
|
country = Column(String(5), nullable=True)
|
|
region = Column(String(100), nullable=True)
|
|
city = Column(String(100), nullable=True)
|
|
|
|
# Technical context
|
|
endpoint = Column(String(255), nullable=True, index=True)
|
|
http_method = Column(String(10), nullable=True)
|
|
status_code = Column(Integer, nullable=True)
|
|
response_time_ms = Column(Integer, nullable=True)
|
|
|
|
# Resource context
|
|
resource_type = Column(String(50), nullable=True, index=True) # file, customer, document, etc.
|
|
resource_id = Column(String(100), nullable=True, index=True)
|
|
resource_name = Column(String(255), nullable=True)
|
|
|
|
# Data context
|
|
data_before = Column(Text, nullable=True) # JSON string of previous state
|
|
data_after = Column(Text, nullable=True) # JSON string of new state
|
|
data_volume = Column(Integer, nullable=True) # Bytes processed
|
|
record_count = Column(Integer, nullable=True) # Number of records affected
|
|
|
|
# Risk assessment
|
|
risk_score = Column(Integer, default=0, nullable=False, index=True) # 0-100
|
|
risk_factors = Column(Text, nullable=True) # JSON array of risk indicators
|
|
threat_indicators = Column(Text, nullable=True) # JSON array of threat patterns
|
|
|
|
# Compliance tracking
|
|
compliance_standards = Column(Text, nullable=True) # JSON array of applicable standards
|
|
retention_period_days = Column(Integer, default=2555, nullable=False) # 7 years default
|
|
|
|
# Timestamp and tracking
|
|
timestamp = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), nullable=False, index=True)
|
|
processed_at = Column(DateTime(timezone=True), nullable=True)
|
|
correlation_id = Column(String(64), nullable=True, index=True) # For related events
|
|
|
|
# Additional metadata
|
|
tags = Column(Text, nullable=True) # JSON array of tags for categorization
|
|
custom_fields = Column(Text, nullable=True) # JSON object for custom data
|
|
|
|
# Relationships
|
|
user = relationship("User", foreign_keys=[user_id])
|
|
impersonated_user = relationship("User", foreign_keys=[impersonated_user_id])
|
|
|
|
def set_data_before(self, data: Dict[str, Any]) -> None:
|
|
"""Set data before change as JSON"""
|
|
self.data_before = json.dumps(data, default=str) if data else None
|
|
|
|
def set_data_after(self, data: Dict[str, Any]) -> None:
|
|
"""Set data after change as JSON"""
|
|
self.data_after = json.dumps(data, default=str) if data else None
|
|
|
|
def get_data_before(self) -> Optional[Dict[str, Any]]:
|
|
"""Get data before change from JSON"""
|
|
return json.loads(self.data_before) if self.data_before else None
|
|
|
|
def get_data_after(self) -> Optional[Dict[str, Any]]:
|
|
"""Get data after change from JSON"""
|
|
return json.loads(self.data_after) if self.data_after else None
|
|
|
|
def set_risk_factors(self, factors: list) -> None:
|
|
"""Set risk factors as JSON"""
|
|
self.risk_factors = json.dumps(factors) if factors else None
|
|
|
|
def get_risk_factors(self) -> list:
|
|
"""Get risk factors from JSON"""
|
|
return json.loads(self.risk_factors) if self.risk_factors else []
|
|
|
|
def set_threat_indicators(self, indicators: list) -> None:
|
|
"""Set threat indicators as JSON"""
|
|
self.threat_indicators = json.dumps(indicators) if indicators else None
|
|
|
|
def get_threat_indicators(self) -> list:
|
|
"""Get threat indicators from JSON"""
|
|
return json.loads(self.threat_indicators) if self.threat_indicators else []
|
|
|
|
def set_compliance_standards(self, standards: list) -> None:
|
|
"""Set compliance standards as JSON"""
|
|
self.compliance_standards = json.dumps(standards) if standards else None
|
|
|
|
def get_compliance_standards(self) -> list:
|
|
"""Get compliance standards from JSON"""
|
|
return json.loads(self.compliance_standards) if self.compliance_standards else []
|
|
|
|
def set_tags(self, tags: list) -> None:
|
|
"""Set tags as JSON"""
|
|
self.tags = json.dumps(tags) if tags else None
|
|
|
|
def get_tags(self) -> list:
|
|
"""Get tags from JSON"""
|
|
return json.loads(self.tags) if self.tags else []
|
|
|
|
def set_custom_fields(self, fields: Dict[str, Any]) -> None:
|
|
"""Set custom fields as JSON"""
|
|
self.custom_fields = json.dumps(fields, default=str) if fields else None
|
|
|
|
def get_custom_fields(self) -> Optional[Dict[str, Any]]:
|
|
"""Get custom fields from JSON"""
|
|
return json.loads(self.custom_fields) if self.custom_fields else None
|
|
|
|
# Add indexes for performance
|
|
__table_args__ = (
|
|
Index('idx_enhanced_audit_user_timestamp', 'user_id', 'timestamp'),
|
|
Index('idx_enhanced_audit_event_severity', 'event_type', 'severity'),
|
|
Index('idx_enhanced_audit_resource', 'resource_type', 'resource_id'),
|
|
Index('idx_enhanced_audit_ip_timestamp', 'source_ip', 'timestamp'),
|
|
Index('idx_enhanced_audit_correlation', 'correlation_id'),
|
|
Index('idx_enhanced_audit_risk_score', 'risk_score'),
|
|
Index('idx_enhanced_audit_compliance', 'compliance_standards'),
|
|
)
|
|
|
|
|
|
class SecurityAlert(BaseModel):
|
|
"""
|
|
Security alerts for real-time monitoring and incident response
|
|
"""
|
|
__tablename__ = "security_alerts"
|
|
|
|
id = Column(Integer, primary_key=True, autoincrement=True, index=True)
|
|
|
|
# Alert identification
|
|
alert_id = Column(String(64), nullable=False, unique=True, index=True)
|
|
rule_id = Column(String(64), nullable=False, index=True)
|
|
rule_name = Column(String(255), nullable=False)
|
|
|
|
# Alert details
|
|
title = Column(String(255), nullable=False)
|
|
description = Column(Text, nullable=False)
|
|
severity = Column(String(20), nullable=False, index=True)
|
|
confidence = Column(Integer, default=100, nullable=False) # 0-100 confidence score
|
|
|
|
# Context
|
|
event_count = Column(Integer, default=1, nullable=False) # Number of triggering events
|
|
time_window_minutes = Column(Integer, nullable=True) # Time window for correlation
|
|
affected_users = Column(Text, nullable=True) # JSON array of user IDs
|
|
affected_resources = Column(Text, nullable=True) # JSON array of resource identifiers
|
|
|
|
# Response tracking
|
|
status = Column(String(20), default="open", nullable=False, index=True) # open, investigating, resolved, false_positive
|
|
assigned_to = Column(Integer, ForeignKey("users.id"), nullable=True)
|
|
resolved_by = Column(Integer, ForeignKey("users.id"), nullable=True)
|
|
resolution_notes = Column(Text, nullable=True)
|
|
|
|
# Timestamps
|
|
first_seen = Column(DateTime(timezone=True), nullable=False, index=True)
|
|
last_seen = Column(DateTime(timezone=True), nullable=False, index=True)
|
|
acknowledged_at = Column(DateTime(timezone=True), nullable=True)
|
|
resolved_at = Column(DateTime(timezone=True), nullable=True)
|
|
|
|
# Related audit logs
|
|
triggering_events = Column(Text, nullable=True) # JSON array of audit log IDs
|
|
|
|
# Additional metadata
|
|
tags = Column(Text, nullable=True) # JSON array of tags
|
|
custom_fields = Column(Text, nullable=True) # JSON object for custom data
|
|
|
|
# Relationships
|
|
assignee = relationship("User", foreign_keys=[assigned_to])
|
|
resolver = relationship("User", foreign_keys=[resolved_by])
|
|
|
|
|
|
class ComplianceReport(BaseModel):
|
|
"""
|
|
Compliance reporting for various standards
|
|
"""
|
|
__tablename__ = "compliance_reports"
|
|
|
|
id = Column(Integer, primary_key=True, autoincrement=True, index=True)
|
|
|
|
# Report identification
|
|
report_id = Column(String(64), nullable=False, unique=True, index=True)
|
|
standard = Column(String(50), nullable=False, index=True)
|
|
report_type = Column(String(50), nullable=False, index=True) # periodic, on_demand, incident
|
|
|
|
# Report details
|
|
title = Column(String(255), nullable=False)
|
|
description = Column(Text, nullable=True)
|
|
|
|
# Time range
|
|
start_date = Column(DateTime(timezone=True), nullable=False, index=True)
|
|
end_date = Column(DateTime(timezone=True), nullable=False, index=True)
|
|
|
|
# Report content
|
|
summary = Column(Text, nullable=True) # JSON summary of findings
|
|
details = Column(Text, nullable=True) # JSON detailed findings
|
|
recommendations = Column(Text, nullable=True) # JSON recommendations
|
|
|
|
# Metrics
|
|
total_events = Column(Integer, default=0, nullable=False)
|
|
security_events = Column(Integer, default=0, nullable=False)
|
|
violations = Column(Integer, default=0, nullable=False)
|
|
high_risk_events = Column(Integer, default=0, nullable=False)
|
|
|
|
# Status
|
|
status = Column(String(20), default="generating", nullable=False, index=True) # generating, ready, delivered, archived
|
|
generated_by = Column(Integer, ForeignKey("users.id"), nullable=False)
|
|
generated_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), nullable=False)
|
|
|
|
# Delivery
|
|
recipients = Column(Text, nullable=True) # JSON array of recipient emails
|
|
delivered_at = Column(DateTime(timezone=True), nullable=True)
|
|
|
|
# File storage
|
|
file_path = Column(String(500), nullable=True) # Path to generated report file
|
|
file_size = Column(Integer, nullable=True) # File size in bytes
|
|
|
|
# Relationships
|
|
generator = relationship("User", foreign_keys=[generated_by])
|
|
|
|
|
|
class AuditRetentionPolicy(BaseModel):
|
|
"""
|
|
Audit log retention policies for compliance
|
|
"""
|
|
__tablename__ = "audit_retention_policies"
|
|
|
|
id = Column(Integer, primary_key=True, autoincrement=True, index=True)
|
|
|
|
# Policy identification
|
|
policy_name = Column(String(255), nullable=False, unique=True, index=True)
|
|
event_types = Column(Text, nullable=True) # JSON array of event types to apply to
|
|
compliance_standards = Column(Text, nullable=True) # JSON array of applicable standards
|
|
|
|
# Retention settings
|
|
retention_days = Column(Integer, nullable=False) # Days to retain
|
|
archive_after_days = Column(Integer, nullable=True) # Days before archiving
|
|
|
|
# Policy details
|
|
description = Column(Text, nullable=True)
|
|
is_active = Column(Boolean, default=True, nullable=False)
|
|
priority = Column(Integer, default=100, nullable=False) # Higher priority = more specific
|
|
|
|
# Timestamps
|
|
created_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), nullable=False)
|
|
updated_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), nullable=False)
|
|
created_by = Column(Integer, ForeignKey("users.id"), nullable=False)
|
|
|
|
# Relationships
|
|
creator = relationship("User")
|
|
|
|
|
|
class SIEMIntegration(BaseModel):
|
|
"""
|
|
SIEM integration configuration and status
|
|
"""
|
|
__tablename__ = "siem_integrations"
|
|
|
|
id = Column(Integer, primary_key=True, autoincrement=True, index=True)
|
|
|
|
# Integration identification
|
|
integration_name = Column(String(255), nullable=False, unique=True, index=True)
|
|
siem_type = Column(String(50), nullable=False, index=True) # splunk, elk, qradar, etc.
|
|
|
|
# Configuration
|
|
endpoint_url = Column(String(500), nullable=True)
|
|
api_key_hash = Column(String(255), nullable=True) # Hashed API key
|
|
configuration = Column(Text, nullable=True) # JSON configuration
|
|
|
|
# Event filtering
|
|
event_types = Column(Text, nullable=True) # JSON array of event types to send
|
|
severity_threshold = Column(String(20), default="medium", nullable=False)
|
|
|
|
# Status
|
|
is_active = Column(Boolean, default=True, nullable=False)
|
|
is_healthy = Column(Boolean, default=True, nullable=False)
|
|
last_sync = Column(DateTime(timezone=True), nullable=True)
|
|
last_error = Column(Text, nullable=True)
|
|
|
|
# Statistics
|
|
events_sent = Column(Integer, default=0, nullable=False)
|
|
errors_count = Column(Integer, default=0, nullable=False)
|
|
|
|
# Timestamps
|
|
created_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), nullable=False)
|
|
updated_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), nullable=False)
|
|
created_by = Column(Integer, ForeignKey("users.id"), nullable=False)
|
|
|
|
# Relationships
|
|
creator = relationship("User")
|