package models import ( "crypto/sha256" "fmt" "time" "github.com/google/uuid" ) // SecurityEvent represents a security-related event that occurred type SecurityEvent struct { Timestamp time.Time `json:"timestamp" db:"timestamp"` Level string `json:"level" db:"level"` // CRITICAL, WARNING, INFO, DEBUG EventType string `json:"event_type" db:"event_type"` AgentID uuid.UUID `json:"agent_id,omitempty" db:"agent_id"` Message string `json:"message" db:"message"` TraceID string `json:"trace_id,omitempty" db:"trace_id"` IPAddress string `json:"ip_address,omitempty" db:"ip_address"` Details map[string]interface{} `json:"details,omitempty" db:"details"` // JSON encoded Metadata map[string]interface{} `json:"metadata,omitempty" db:"metadata"` // JSON encoded } // SecurityEventTypes defines all possible security event types var SecurityEventTypes = struct { CmdSigned string CmdSignatureVerificationFailed string CmdSignatureVerificationSuccess string UpdateNonceInvalid string UpdateSignatureVerificationFailed string MachineIDMismatch string AuthJWTValidationFailed string PrivateKeyNotConfigured string AgentRegistrationFailed string UnauthorizedAccessAttempt string ConfigTamperingDetected string AnomalousBehavior string }{ CmdSigned: "CMD_SIGNED", CmdSignatureVerificationFailed: "CMD_SIGNATURE_VERIFICATION_FAILED", CmdSignatureVerificationSuccess: "CMD_SIGNATURE_VERIFICATION_SUCCESS", UpdateNonceInvalid: "UPDATE_NONCE_INVALID", UpdateSignatureVerificationFailed: "UPDATE_SIGNATURE_VERIFICATION_FAILED", MachineIDMismatch: "MACHINE_ID_MISMATCH", AuthJWTValidationFailed: "AUTH_JWT_VALIDATION_FAILED", PrivateKeyNotConfigured: "PRIVATE_KEY_NOT_CONFIGURED", AgentRegistrationFailed: "AGENT_REGISTRATION_FAILED", UnauthorizedAccessAttempt: "UNAUTHORIZED_ACCESS_ATTEMPT", ConfigTamperingDetected: "CONFIG_TAMPERING_DETECTED", AnomalousBehavior: "ANOMALOUS_BEHAVIOR", } // IsCritical returns true if the event is of critical severity func (e *SecurityEvent) IsCritical() bool { return e.Level == "CRITICAL" } // IsWarning returns true if the event is a warning func (e *SecurityEvent) IsWarning() bool { return e.Level == "WARNING" } // ShouldLogToDatabase determines if this event should be stored in the database func (e *SecurityEvent) ShouldLogToDatabase(logToDatabase bool) bool { return logToDatabase && (e.IsCritical() || e.IsWarning()) } // HashIPAddress hashes the IP address for privacy func (e *SecurityEvent) HashIPAddress() { if e.IPAddress != "" { hash := sha256.Sum256([]byte(e.IPAddress)) e.IPAddress = fmt.Sprintf("hashed:%x", hash[:8]) // Store first 8 bytes of hash } } // NewSecurityEvent creates a new security event with current timestamp func NewSecurityEvent(level, eventType string, agentID uuid.UUID, message string) *SecurityEvent { return &SecurityEvent{ Timestamp: time.Now().UTC(), Level: level, EventType: eventType, AgentID: agentID, Message: message, Details: make(map[string]interface{}), Metadata: make(map[string]interface{}), } } // WithTrace adds a trace ID to the event func (e *SecurityEvent) WithTrace(traceID string) *SecurityEvent { e.TraceID = traceID return e } // WithIPAddress adds an IP address to the event func (e *SecurityEvent) WithIPAddress(ip string) *SecurityEvent { e.IPAddress = ip return e } // WithDetail adds a key-value detail to the event func (e *SecurityEvent) WithDetail(key string, value interface{}) *SecurityEvent { e.Details[key] = value return e } // WithMetadata adds a key-value metadata to the event func (e *SecurityEvent) WithMetadata(key string, value interface{}) *SecurityEvent { e.Metadata[key] = value return e }