monorepo/native/desktop/maplefile/internal/service/securitylog/securitylog.go

276 lines
8.1 KiB
Go

// Package securitylog provides security event logging for audit purposes.
// This captures security-relevant events for monitoring and forensics.
package securitylog
import (
"time"
"go.uber.org/zap"
)
// EventType defines the type of security event
type EventType string
const (
// Authentication events
EventLoginAttempt EventType = "LOGIN_ATTEMPT"
EventLoginSuccess EventType = "LOGIN_SUCCESS"
EventLoginFailure EventType = "LOGIN_FAILURE"
EventLogout EventType = "LOGOUT"
EventSessionRestored EventType = "SESSION_RESTORED"
EventSessionExpired EventType = "SESSION_EXPIRED"
EventSessionRevoked EventType = "SESSION_REVOKED"
EventTokenRefresh EventType = "TOKEN_REFRESH"
EventTokenRefreshFail EventType = "TOKEN_REFRESH_FAILURE"
// Registration events
EventRegistration EventType = "REGISTRATION"
EventEmailVerification EventType = "EMAIL_VERIFICATION"
EventOTTRequest EventType = "OTT_REQUEST"
EventOTTVerify EventType = "OTT_VERIFY"
EventPasswordChallenge EventType = "PASSWORD_CHALLENGE"
// Rate limiting events
EventRateLimitExceeded EventType = "RATE_LIMIT_EXCEEDED"
// Data access events
EventCollectionCreate EventType = "COLLECTION_CREATE"
EventCollectionUpdate EventType = "COLLECTION_UPDATE"
EventCollectionDelete EventType = "COLLECTION_DELETE"
EventCollectionAccess EventType = "COLLECTION_ACCESS"
EventFileUpload EventType = "FILE_UPLOAD"
EventFileDownload EventType = "FILE_DOWNLOAD"
EventFileDelete EventType = "FILE_DELETE"
EventFileAccess EventType = "FILE_ACCESS"
EventFileOpen EventType = "FILE_OPEN"
// Export events
EventExportStart EventType = "EXPORT_START"
EventExportComplete EventType = "EXPORT_COMPLETE"
EventExportFailure EventType = "EXPORT_FAILURE"
// Configuration events
EventConfigChange EventType = "CONFIG_CHANGE"
EventConfigIntegrityFail EventType = "CONFIG_INTEGRITY_FAILURE"
EventCloudProviderChange EventType = "CLOUD_PROVIDER_CHANGE"
// Security events
EventSecurityValidationFail EventType = "SECURITY_VALIDATION_FAILURE"
EventURLValidationFail EventType = "URL_VALIDATION_FAILURE"
EventInputValidationFail EventType = "INPUT_VALIDATION_FAILURE"
EventPathTraversalAttempt EventType = "PATH_TRAVERSAL_ATTEMPT"
// Key management events
EventMasterKeyDerived EventType = "MASTER_KEY_DERIVED"
EventMasterKeyCleared EventType = "MASTER_KEY_CLEARED"
EventPasswordCleared EventType = "PASSWORD_CLEARED"
// Application lifecycle events
EventAppStart EventType = "APP_START"
EventAppShutdown EventType = "APP_SHUTDOWN"
)
// EventOutcome indicates the result of an event
type EventOutcome string
const (
OutcomeSuccess EventOutcome = "SUCCESS"
OutcomeFailure EventOutcome = "FAILURE"
OutcomeBlocked EventOutcome = "BLOCKED"
)
// SecurityEvent represents a security-relevant event
type SecurityEvent struct {
Timestamp time.Time `json:"timestamp"`
EventType EventType `json:"event_type"`
Outcome EventOutcome `json:"outcome"`
UserEmail string `json:"user_email,omitempty"` // Masked email
ResourceID string `json:"resource_id,omitempty"`
ResourceType string `json:"resource_type,omitempty"`
Details map[string]string `json:"details,omitempty"`
ErrorMsg string `json:"error,omitempty"`
}
// Service provides security event logging
type Service struct {
logger *zap.Logger
}
// New creates a new security logging service
func New(logger *zap.Logger) *Service {
return &Service{
logger: logger.Named("security"),
}
}
// ProvideService is the Wire provider for the security log service
func ProvideService(logger *zap.Logger) *Service {
return New(logger)
}
// LogEvent logs a security event
func (s *Service) LogEvent(event *SecurityEvent) {
event.Timestamp = time.Now().UTC()
fields := []zap.Field{
zap.String("event_type", string(event.EventType)),
zap.String("outcome", string(event.Outcome)),
zap.Time("timestamp", event.Timestamp),
}
if event.UserEmail != "" {
fields = append(fields, zap.String("user_email", event.UserEmail))
}
if event.ResourceID != "" {
fields = append(fields, zap.String("resource_id", event.ResourceID))
}
if event.ResourceType != "" {
fields = append(fields, zap.String("resource_type", event.ResourceType))
}
if event.ErrorMsg != "" {
fields = append(fields, zap.String("error", event.ErrorMsg))
}
for k, v := range event.Details {
fields = append(fields, zap.String("detail_"+k, v))
}
switch event.Outcome {
case OutcomeSuccess:
s.logger.Info("Security event", fields...)
case OutcomeFailure:
s.logger.Warn("Security event", fields...)
case OutcomeBlocked:
s.logger.Warn("Security event (blocked)", fields...)
default:
s.logger.Info("Security event", fields...)
}
}
// Helper methods for common events
// LogLoginAttempt logs a login attempt
func (s *Service) LogLoginAttempt(maskedEmail string) {
s.LogEvent(&SecurityEvent{
EventType: EventLoginAttempt,
Outcome: OutcomeSuccess,
UserEmail: maskedEmail,
})
}
// LogLoginSuccess logs a successful login
func (s *Service) LogLoginSuccess(maskedEmail string) {
s.LogEvent(&SecurityEvent{
EventType: EventLoginSuccess,
Outcome: OutcomeSuccess,
UserEmail: maskedEmail,
})
}
// LogLoginFailure logs a failed login
func (s *Service) LogLoginFailure(maskedEmail string, reason string) {
s.LogEvent(&SecurityEvent{
EventType: EventLoginFailure,
Outcome: OutcomeFailure,
UserEmail: maskedEmail,
ErrorMsg: reason,
})
}
// LogLogout logs a logout event
func (s *Service) LogLogout(maskedEmail string) {
s.LogEvent(&SecurityEvent{
EventType: EventLogout,
Outcome: OutcomeSuccess,
UserEmail: maskedEmail,
})
}
// LogRateLimitExceeded logs a rate limit exceeded event
func (s *Service) LogRateLimitExceeded(maskedEmail string, operation string) {
s.LogEvent(&SecurityEvent{
EventType: EventRateLimitExceeded,
Outcome: OutcomeBlocked,
UserEmail: maskedEmail,
Details: map[string]string{
"operation": operation,
},
})
}
// LogFileAccess logs a file access event
func (s *Service) LogFileAccess(maskedEmail string, fileID string, operation string, outcome EventOutcome) {
s.LogEvent(&SecurityEvent{
EventType: EventFileAccess,
Outcome: outcome,
UserEmail: maskedEmail,
ResourceID: fileID,
ResourceType: "file",
Details: map[string]string{
"operation": operation,
},
})
}
// LogCollectionAccess logs a collection access event
func (s *Service) LogCollectionAccess(maskedEmail string, collectionID string, operation string, outcome EventOutcome) {
s.LogEvent(&SecurityEvent{
EventType: EventCollectionAccess,
Outcome: outcome,
UserEmail: maskedEmail,
ResourceID: collectionID,
ResourceType: "collection",
Details: map[string]string{
"operation": operation,
},
})
}
// LogSecurityValidationFailure logs a security validation failure
func (s *Service) LogSecurityValidationFailure(eventType EventType, details map[string]string, errorMsg string) {
s.LogEvent(&SecurityEvent{
EventType: eventType,
Outcome: OutcomeBlocked,
Details: details,
ErrorMsg: errorMsg,
})
}
// LogExport logs an export operation
func (s *Service) LogExport(maskedEmail string, eventType EventType, outcome EventOutcome, details map[string]string) {
s.LogEvent(&SecurityEvent{
EventType: eventType,
Outcome: outcome,
UserEmail: maskedEmail,
Details: details,
})
}
// LogConfigChange logs a configuration change
func (s *Service) LogConfigChange(setting string, maskedEmail string) {
s.LogEvent(&SecurityEvent{
EventType: EventConfigChange,
Outcome: OutcomeSuccess,
UserEmail: maskedEmail,
Details: map[string]string{
"setting": setting,
},
})
}
// LogAppLifecycle logs application start/shutdown
func (s *Service) LogAppLifecycle(eventType EventType) {
s.LogEvent(&SecurityEvent{
EventType: eventType,
Outcome: OutcomeSuccess,
})
}
// LogKeyManagement logs key management operations
func (s *Service) LogKeyManagement(eventType EventType, maskedEmail string, outcome EventOutcome) {
s.LogEvent(&SecurityEvent{
EventType: eventType,
Outcome: outcome,
UserEmail: maskedEmail,
})
}