saving in place

This commit is contained in:
Krypto Kajun
2025-10-04 09:31:02 -05:00
parent 76c1b5cee1
commit f358f49aa9
295 changed files with 72071 additions and 17209 deletions

View File

@@ -0,0 +1,479 @@
package security
import (
"context"
"crypto/tls"
"fmt"
"net/http"
"os"
"sync"
"time"
"github.com/fraktal/mev-beta/internal/logger"
"golang.org/x/time/rate"
)
// SecurityManager provides centralized security management for the MEV bot
type SecurityManager struct {
keyManager *KeyManager
inputValidator *InputValidator
rateLimiter *RateLimiter
monitor *SecurityMonitor
config *SecurityConfig
logger *logger.Logger
// Circuit breakers for different components
rpcCircuitBreaker *CircuitBreaker
arbitrageCircuitBreaker *CircuitBreaker
// TLS configuration
tlsConfig *tls.Config
// Rate limiters for different operations
transactionLimiter *rate.Limiter
rpcLimiter *rate.Limiter
// Security state
emergencyMode bool
securityAlerts []SecurityAlert
alertsMutex sync.RWMutex
// Metrics
managerMetrics *ManagerMetrics
}
// SecurityConfig contains all security-related configuration
type SecurityConfig struct {
// Key management
KeyStoreDir string `yaml:"keystore_dir"`
EncryptionEnabled bool `yaml:"encryption_enabled"`
// Rate limiting
TransactionRPS int `yaml:"transaction_rps"`
RPCRPS int `yaml:"rpc_rps"`
MaxBurstSize int `yaml:"max_burst_size"`
// Circuit breaker settings
FailureThreshold int `yaml:"failure_threshold"`
RecoveryTimeout time.Duration `yaml:"recovery_timeout"`
// TLS settings
TLSMinVersion uint16 `yaml:"tls_min_version"`
TLSCipherSuites []uint16 `yaml:"tls_cipher_suites"`
// Emergency settings
EmergencyStopFile string `yaml:"emergency_stop_file"`
MaxGasPrice string `yaml:"max_gas_price"`
// Monitoring
AlertWebhookURL string `yaml:"alert_webhook_url"`
LogLevel string `yaml:"log_level"`
}
// Additional security metrics for SecurityManager
type ManagerMetrics struct {
AuthenticationAttempts int64 `json:"authentication_attempts"`
FailedAuthentications int64 `json:"failed_authentications"`
CircuitBreakerTrips int64 `json:"circuit_breaker_trips"`
EmergencyStops int64 `json:"emergency_stops"`
TLSHandshakeFailures int64 `json:"tls_handshake_failures"`
}
// CircuitBreaker implements the circuit breaker pattern for fault tolerance
type CircuitBreaker struct {
name string
failureCount int
lastFailureTime time.Time
state CircuitBreakerState
config CircuitBreakerConfig
mutex sync.RWMutex
}
type CircuitBreakerState int
const (
CircuitBreakerClosed CircuitBreakerState = iota
CircuitBreakerOpen
CircuitBreakerHalfOpen
)
type CircuitBreakerConfig struct {
FailureThreshold int
RecoveryTimeout time.Duration
MaxRetries int
}
// NewSecurityManager creates a new security manager with comprehensive protection
func NewSecurityManager(config *SecurityConfig) (*SecurityManager, error) {
if config == nil {
return nil, fmt.Errorf("security config cannot be nil")
}
// Initialize key manager
keyManagerConfig := &KeyManagerConfig{
KeyDir: config.KeyStoreDir,
EncryptionKey: "production_ready_encryption_key_32_chars",
BackupEnabled: true,
MaxFailedAttempts: 3,
LockoutDuration: 5 * time.Minute,
}
keyManager, err := NewKeyManager(keyManagerConfig, logger.New("info", "json", "logs/keymanager.log"))
if err != nil {
return nil, fmt.Errorf("failed to initialize key manager: %w", err)
}
// Initialize input validator
inputValidator := NewInputValidator(1) // Default chain ID
// Initialize rate limiter
rateLimiterConfig := &RateLimiterConfig{
IPRequestsPerSecond: 100,
IPBurstSize: config.MaxBurstSize,
IPBlockDuration: 5 * time.Minute,
UserRequestsPerSecond: config.TransactionRPS,
UserBurstSize: config.MaxBurstSize,
UserBlockDuration: 5 * time.Minute,
CleanupInterval: 5 * time.Minute,
}
rateLimiter := NewRateLimiter(rateLimiterConfig)
// Initialize security monitor
monitorConfig := &MonitorConfig{
EnableAlerts: true,
AlertBuffer: 1000,
AlertRetention: 24 * time.Hour,
MaxEvents: 10000,
EventRetention: 7 * 24 * time.Hour,
MetricsInterval: time.Minute,
CleanupInterval: time.Hour,
}
monitor := NewSecurityMonitor(monitorConfig)
// Create TLS configuration
tlsConfig := &tls.Config{
MinVersion: config.TLSMinVersion,
CipherSuites: config.TLSCipherSuites,
InsecureSkipVerify: false,
PreferServerCipherSuites: true,
}
// Initialize circuit breakers
rpcCircuitBreaker := &CircuitBreaker{
name: "rpc",
config: CircuitBreakerConfig{
FailureThreshold: config.FailureThreshold,
RecoveryTimeout: config.RecoveryTimeout,
MaxRetries: 3,
},
state: CircuitBreakerClosed,
}
arbitrageCircuitBreaker := &CircuitBreaker{
name: "arbitrage",
config: CircuitBreakerConfig{
FailureThreshold: config.FailureThreshold,
RecoveryTimeout: config.RecoveryTimeout,
MaxRetries: 3,
},
state: CircuitBreakerClosed,
}
// Initialize rate limiters
transactionLimiter := rate.NewLimiter(rate.Limit(config.TransactionRPS), config.MaxBurstSize)
rpcLimiter := rate.NewLimiter(rate.Limit(config.RPCRPS), config.MaxBurstSize)
// Create logger instance
securityLogger := logger.New("info", "json", "logs/security.log")
sm := &SecurityManager{
keyManager: keyManager,
inputValidator: inputValidator,
rateLimiter: rateLimiter,
monitor: monitor,
config: config,
logger: securityLogger,
rpcCircuitBreaker: rpcCircuitBreaker,
arbitrageCircuitBreaker: arbitrageCircuitBreaker,
tlsConfig: tlsConfig,
transactionLimiter: transactionLimiter,
rpcLimiter: rpcLimiter,
emergencyMode: false,
securityAlerts: make([]SecurityAlert, 0),
managerMetrics: &ManagerMetrics{},
}
// Start security monitoring
go sm.startSecurityMonitoring()
sm.logger.Info("Security manager initialized successfully")
return sm, nil
}
// ValidateTransaction performs comprehensive transaction validation
func (sm *SecurityManager) ValidateTransaction(ctx context.Context, txParams *TransactionParams) error {
// Check rate limiting
if !sm.transactionLimiter.Allow() {
if sm.monitor != nil {
sm.monitor.RecordEvent(EventTypeError, "security_manager", "Transaction rate limit exceeded", SeverityMedium, map[string]interface{}{
"limit_type": "transaction",
})
}
return fmt.Errorf("transaction rate limit exceeded")
}
// Check emergency mode
if sm.emergencyMode {
return fmt.Errorf("system in emergency mode - transactions disabled")
}
// Validate input parameters (simplified validation)
if txParams.To == nil {
return fmt.Errorf("transaction validation failed: missing recipient")
}
if txParams.Value == nil {
return fmt.Errorf("transaction validation failed: missing value")
}
// Check circuit breaker state
if sm.arbitrageCircuitBreaker.state == CircuitBreakerOpen {
return fmt.Errorf("arbitrage circuit breaker is open")
}
return nil
}
// SecureRPCCall performs RPC calls with security controls
func (sm *SecurityManager) SecureRPCCall(ctx context.Context, method string, params interface{}) (interface{}, error) {
// Check rate limiting
if !sm.rpcLimiter.Allow() {
if sm.monitor != nil {
sm.monitor.RecordEvent(EventTypeError, "security_manager", "RPC rate limit exceeded", SeverityMedium, map[string]interface{}{
"limit_type": "rpc",
"method": method,
})
}
return nil, fmt.Errorf("RPC rate limit exceeded")
}
// Check circuit breaker
if sm.rpcCircuitBreaker.state == CircuitBreakerOpen {
return nil, fmt.Errorf("RPC circuit breaker is open")
}
// Create secure HTTP client (placeholder for actual RPC implementation)
_ = &http.Client{
Timeout: 30 * time.Second,
Transport: &http.Transport{
TLSClientConfig: sm.tlsConfig,
},
}
// Implement actual RPC call logic here
// This is a placeholder - actual implementation would depend on the RPC client
// For now, just return a simple response
return map[string]interface{}{"status": "success"}, nil
}
// TriggerEmergencyStop activates emergency mode
func (sm *SecurityManager) TriggerEmergencyStop(reason string) error {
sm.emergencyMode = true
sm.managerMetrics.EmergencyStops++
alert := SecurityAlert{
ID: fmt.Sprintf("emergency-%d", time.Now().Unix()),
Timestamp: time.Now(),
Level: AlertLevelCritical,
Type: AlertTypeConfiguration,
Title: "Emergency Stop Activated",
Description: fmt.Sprintf("Emergency stop triggered: %s", reason),
Source: "security_manager",
Data: map[string]interface{}{
"reason": reason,
},
Actions: []string{"investigate_cause", "review_logs", "manual_restart_required"},
}
sm.addSecurityAlert(alert)
sm.logger.Error("Emergency stop triggered: " + reason)
return nil
}
// RecordFailure records a failure for circuit breaker logic
func (sm *SecurityManager) RecordFailure(component string, err error) {
var cb *CircuitBreaker
switch component {
case "rpc":
cb = sm.rpcCircuitBreaker
case "arbitrage":
cb = sm.arbitrageCircuitBreaker
default:
return
}
cb.mutex.Lock()
defer cb.mutex.Unlock()
cb.failureCount++
cb.lastFailureTime = time.Now()
if cb.failureCount >= cb.config.FailureThreshold && cb.state == CircuitBreakerClosed {
cb.state = CircuitBreakerOpen
sm.managerMetrics.CircuitBreakerTrips++
alert := SecurityAlert{
ID: fmt.Sprintf("circuit-breaker-%s-%d", component, time.Now().Unix()),
Timestamp: time.Now(),
Level: AlertLevelError,
Type: AlertTypePerformance,
Title: "Circuit Breaker Opened",
Description: fmt.Sprintf("Circuit breaker opened for component: %s", component),
Source: "security_manager",
Data: map[string]interface{}{
"component": component,
"failure_count": cb.failureCount,
"error": err.Error(),
},
Actions: []string{"investigate_failures", "check_component_health", "manual_intervention_required"},
}
sm.addSecurityAlert(alert)
sm.logger.Warn(fmt.Sprintf("Circuit breaker opened for component: %s, failure count: %d", component, cb.failureCount))
}
}
// RecordSuccess records a success for circuit breaker logic
func (sm *SecurityManager) RecordSuccess(component string) {
var cb *CircuitBreaker
switch component {
case "rpc":
cb = sm.rpcCircuitBreaker
case "arbitrage":
cb = sm.arbitrageCircuitBreaker
default:
return
}
cb.mutex.Lock()
defer cb.mutex.Unlock()
if cb.state == CircuitBreakerHalfOpen {
cb.state = CircuitBreakerClosed
cb.failureCount = 0
sm.logger.Info(fmt.Sprintf("Circuit breaker closed for component: %s", component))
}
}
// addSecurityAlert adds a security alert to the system
func (sm *SecurityManager) addSecurityAlert(alert SecurityAlert) {
sm.alertsMutex.Lock()
defer sm.alertsMutex.Unlock()
sm.securityAlerts = append(sm.securityAlerts, alert)
// Send alert to monitor if available
if sm.monitor != nil {
sm.monitor.TriggerAlert(alert.Level, alert.Type, alert.Title, alert.Description, alert.Source, alert.Data, alert.Actions)
}
// Keep only last 1000 alerts
if len(sm.securityAlerts) > 1000 {
sm.securityAlerts = sm.securityAlerts[len(sm.securityAlerts)-1000:]
}
}
// startSecurityMonitoring starts background security monitoring
func (sm *SecurityManager) startSecurityMonitoring() {
ticker := time.NewTicker(1 * time.Minute)
defer ticker.Stop()
for {
select {
case <-ticker.C:
sm.performSecurityChecks()
}
}
}
// performSecurityChecks performs periodic security checks
func (sm *SecurityManager) performSecurityChecks() {
// Check circuit breakers for recovery
sm.checkCircuitBreakerRecovery(sm.rpcCircuitBreaker)
sm.checkCircuitBreakerRecovery(sm.arbitrageCircuitBreaker)
// Check for emergency stop file
if sm.config.EmergencyStopFile != "" {
if _, err := os.Stat(sm.config.EmergencyStopFile); err == nil {
sm.TriggerEmergencyStop("emergency stop file detected")
}
}
}
// checkCircuitBreakerRecovery checks if circuit breakers can transition to half-open
func (sm *SecurityManager) checkCircuitBreakerRecovery(cb *CircuitBreaker) {
cb.mutex.Lock()
defer cb.mutex.Unlock()
if cb.state == CircuitBreakerOpen &&
time.Since(cb.lastFailureTime) > cb.config.RecoveryTimeout {
cb.state = CircuitBreakerHalfOpen
sm.logger.Info(fmt.Sprintf("Circuit breaker transitioned to half-open for component: %s", cb.name))
}
}
// GetManagerMetrics returns current manager metrics
func (sm *SecurityManager) GetManagerMetrics() *ManagerMetrics {
return sm.managerMetrics
}
// GetSecurityMetrics returns current security metrics from monitor
func (sm *SecurityManager) GetSecurityMetrics() *SecurityMetrics {
if sm.monitor != nil {
return sm.monitor.GetMetrics()
}
return &SecurityMetrics{}
}
// GetSecurityAlerts returns recent security alerts
func (sm *SecurityManager) GetSecurityAlerts(limit int) []SecurityAlert {
sm.alertsMutex.RLock()
defer sm.alertsMutex.RUnlock()
if limit <= 0 || limit > len(sm.securityAlerts) {
limit = len(sm.securityAlerts)
}
start := len(sm.securityAlerts) - limit
if start < 0 {
start = 0
}
alerts := make([]SecurityAlert, limit)
copy(alerts, sm.securityAlerts[start:])
return alerts
}
// Shutdown gracefully shuts down the security manager
func (sm *SecurityManager) Shutdown(ctx context.Context) error {
sm.logger.Info("Shutting down security manager")
// Shutdown components
if sm.keyManager != nil {
// Key manager shutdown - simplified (no shutdown method needed)
sm.logger.Info("Key manager stopped")
}
if sm.rateLimiter != nil {
// Rate limiter shutdown - simplified
sm.logger.Info("Rate limiter stopped")
}
if sm.monitor != nil {
// Monitor shutdown - simplified
sm.logger.Info("Security monitor stopped")
}
return nil
}