mirror of
https://github.com/StarFleetCPTN/GoMFT.git
synced 2026-10-17 11:38:15 +02:00
feat: Implement storage provider management functionality
- Added new routes and handlers for managing storage providers, including creation, editing, and deletion. - Introduced a new StorageProvider form component for user input. - Enhanced the database schema to support storage provider references in transfer configurations. - Implemented encryption for sensitive fields in storage provider data. - Added tests for storage provider API endpoints and integration with the database. - Updated frontend components to support storage provider selection and testing.
This commit is contained in:
1 parent
88d0ac815a
commit
31871bd16e
59 files changed
+15842
-594
No files matched your search
@@ -0,0 +1,271 @@
|
||||
package audit
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// SecurityMonitor provides aggregate monitoring, alerting, and reporting for security events
|
||||
type SecurityMonitor struct {
|
||||
auditor *SecurityAuditor
|
||||
statsMutex sync.RWMutex
|
||||
eventCounts map[EventType]int
|
||||
errorCounts map[string]int
|
||||
lastEventTime map[EventType]time.Time
|
||||
alertThresholds map[EventType]int
|
||||
alertHandler AlertHandler
|
||||
}
|
||||
|
||||
// AlertLevel represents the severity of a security alert
|
||||
type AlertLevel string
|
||||
|
||||
// Alert levels
|
||||
const (
|
||||
AlertLevelInfo AlertLevel = "info"
|
||||
AlertLevelWarning AlertLevel = "warning"
|
||||
AlertLevelCritical AlertLevel = "critical"
|
||||
)
|
||||
|
||||
// SecurityAlert represents a security alert to be sent to handlers
|
||||
type SecurityAlert struct {
|
||||
Timestamp time.Time
|
||||
Level AlertLevel
|
||||
EventType EventType
|
||||
Message string
|
||||
Count int
|
||||
Details map[string]interface{}
|
||||
}
|
||||
|
||||
// AlertHandler is the interface for handling security alerts
|
||||
type AlertHandler interface {
|
||||
HandleAlert(alert SecurityAlert)
|
||||
}
|
||||
|
||||
// DefaultAlertHandler is a basic implementation of AlertHandler that logs to a file
|
||||
type DefaultAlertHandler struct {
|
||||
logFile string
|
||||
writer io.Writer
|
||||
writerLock sync.Mutex
|
||||
}
|
||||
|
||||
// NewDefaultAlertHandler creates a new default alert handler
|
||||
func NewDefaultAlertHandler(logFile string) (*DefaultAlertHandler, error) {
|
||||
var writer io.Writer
|
||||
|
||||
if logFile == "" {
|
||||
writer = os.Stdout
|
||||
} else {
|
||||
file, err := os.OpenFile(logFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to open alert log file: %w", err)
|
||||
}
|
||||
writer = file
|
||||
}
|
||||
|
||||
return &DefaultAlertHandler{
|
||||
logFile: logFile,
|
||||
writer: writer,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// HandleAlert logs the alert to the configured output
|
||||
func (h *DefaultAlertHandler) HandleAlert(alert SecurityAlert) {
|
||||
h.writerLock.Lock()
|
||||
defer h.writerLock.Unlock()
|
||||
|
||||
jsonData, err := json.Marshal(alert)
|
||||
if err != nil {
|
||||
fmt.Fprintf(h.writer, "Error marshaling alert: %v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Fprintln(h.writer, string(jsonData))
|
||||
}
|
||||
|
||||
// Close closes any open resources
|
||||
func (h *DefaultAlertHandler) Close() error {
|
||||
if h.logFile != "" {
|
||||
if closer, ok := h.writer.(io.Closer); ok {
|
||||
return closer.Close()
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewSecurityMonitor creates a new SecurityMonitor
|
||||
func NewSecurityMonitor(auditor *SecurityAuditor) *SecurityMonitor {
|
||||
// Use provided auditor or global one if nil
|
||||
if auditor == nil {
|
||||
auditor = GetGlobalAuditor()
|
||||
}
|
||||
|
||||
defaultHandler, _ := NewDefaultAlertHandler("")
|
||||
|
||||
return &SecurityMonitor{
|
||||
auditor: auditor,
|
||||
eventCounts: make(map[EventType]int),
|
||||
errorCounts: make(map[string]int),
|
||||
lastEventTime: make(map[EventType]time.Time),
|
||||
alertThresholds: make(map[EventType]int),
|
||||
alertHandler: defaultHandler,
|
||||
}
|
||||
}
|
||||
|
||||
// SetAlertHandler sets a custom alert handler
|
||||
func (m *SecurityMonitor) SetAlertHandler(handler AlertHandler) {
|
||||
m.alertHandler = handler
|
||||
}
|
||||
|
||||
// SetAlertThreshold sets the threshold for when to generate alerts for a specific event type
|
||||
func (m *SecurityMonitor) SetAlertThreshold(eventType EventType, threshold int) {
|
||||
m.statsMutex.Lock()
|
||||
defer m.statsMutex.Unlock()
|
||||
|
||||
m.alertThresholds[eventType] = threshold
|
||||
}
|
||||
|
||||
// ProcessEvent processes a security event for monitoring
|
||||
func (m *SecurityMonitor) ProcessEvent(event AuditEvent) {
|
||||
m.statsMutex.Lock()
|
||||
defer m.statsMutex.Unlock()
|
||||
|
||||
// Update event statistics
|
||||
m.eventCounts[event.EventType]++
|
||||
m.lastEventTime[event.EventType] = event.Timestamp
|
||||
|
||||
// Track errors
|
||||
if !event.Success && event.Error != "" {
|
||||
errorType := classifyError(event.Error)
|
||||
m.errorCounts[errorType]++
|
||||
|
||||
// Alert on specific error types
|
||||
if strings.Contains(event.Error, "unauthorized") ||
|
||||
strings.Contains(event.Error, "permission") ||
|
||||
strings.Contains(event.Error, "access denied") {
|
||||
m.generateAlert(AlertLevelCritical, event.EventType,
|
||||
fmt.Sprintf("Possible security breach detected: %s", event.Error),
|
||||
map[string]interface{}{
|
||||
"operation": event.Operation,
|
||||
"error": event.Error,
|
||||
"keyVersion": event.KeyVersion,
|
||||
"modelType": event.ModelType,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Check thresholds for alerting
|
||||
threshold, hasThreshold := m.alertThresholds[event.EventType]
|
||||
if hasThreshold && m.eventCounts[event.EventType] >= threshold {
|
||||
if event.EventType == EventDecryptionFailure || event.EventType == EventEncryptionFailure {
|
||||
m.generateAlert(AlertLevelWarning, event.EventType,
|
||||
fmt.Sprintf("High number of %s events detected (%d)", event.EventType, m.eventCounts[event.EventType]),
|
||||
map[string]interface{}{
|
||||
"count": m.eventCounts[event.EventType],
|
||||
"threshold": threshold,
|
||||
})
|
||||
} else if event.EventType == EventKeyRotation {
|
||||
m.generateAlert(AlertLevelInfo, event.EventType,
|
||||
fmt.Sprintf("Key rotation threshold reached (%d operations)", m.eventCounts[event.EventType]),
|
||||
map[string]interface{}{
|
||||
"count": m.eventCounts[event.EventType],
|
||||
"threshold": threshold,
|
||||
})
|
||||
}
|
||||
|
||||
// Reset counter after alerting
|
||||
m.eventCounts[event.EventType] = 0
|
||||
}
|
||||
}
|
||||
|
||||
// GenerateReport generates a report of security events for a time period
|
||||
func (m *SecurityMonitor) GenerateReport(startTime, endTime time.Time, writer io.Writer) error {
|
||||
m.statsMutex.RLock()
|
||||
defer m.statsMutex.RUnlock()
|
||||
|
||||
report := struct {
|
||||
TimeRange struct {
|
||||
Start time.Time `json:"start"`
|
||||
End time.Time `json:"end"`
|
||||
} `json:"time_range"`
|
||||
EventCounts map[EventType]int `json:"event_counts"`
|
||||
ErrorCounts map[string]int `json:"error_counts"`
|
||||
LastEventTimes map[EventType]time.Time `json:"last_event_times"`
|
||||
GeneratedAt time.Time `json:"generated_at"`
|
||||
}{
|
||||
TimeRange: struct {
|
||||
Start time.Time `json:"start"`
|
||||
End time.Time `json:"end"`
|
||||
}{
|
||||
Start: startTime,
|
||||
End: endTime,
|
||||
},
|
||||
EventCounts: m.eventCounts,
|
||||
ErrorCounts: m.errorCounts,
|
||||
LastEventTimes: m.lastEventTime,
|
||||
GeneratedAt: time.Now(),
|
||||
}
|
||||
|
||||
jsonData, err := json.MarshalIndent(report, "", " ")
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to marshal report: %w", err)
|
||||
}
|
||||
|
||||
_, err = writer.Write(jsonData)
|
||||
return err
|
||||
}
|
||||
|
||||
// generateAlert creates and sends a security alert
|
||||
func (m *SecurityMonitor) generateAlert(level AlertLevel, eventType EventType, message string, details map[string]interface{}) {
|
||||
if m.alertHandler == nil {
|
||||
return
|
||||
}
|
||||
|
||||
alert := SecurityAlert{
|
||||
Timestamp: time.Now(),
|
||||
Level: level,
|
||||
EventType: eventType,
|
||||
Message: message,
|
||||
Count: m.eventCounts[eventType],
|
||||
Details: details,
|
||||
}
|
||||
|
||||
go m.alertHandler.HandleAlert(alert)
|
||||
}
|
||||
|
||||
// classifyError examines an error string and categorizes it
|
||||
func classifyError(errorStr string) string {
|
||||
errorStr = strings.ToLower(errorStr)
|
||||
|
||||
if strings.Contains(errorStr, "decrypt") {
|
||||
return "decryption_error"
|
||||
} else if strings.Contains(errorStr, "encrypt") {
|
||||
return "encryption_error"
|
||||
} else if strings.Contains(errorStr, "key") {
|
||||
return "key_error"
|
||||
} else if strings.Contains(errorStr, "permission") || strings.Contains(errorStr, "unauthorized") {
|
||||
return "permission_error"
|
||||
} else {
|
||||
return "other_error"
|
||||
}
|
||||
}
|
||||
|
||||
// AttachToAuditor creates a wrapper function for the auditor's LogEvent method
|
||||
// that processes events through the monitor before passing them to the original function.
|
||||
// Returns the wrapped function that should be set on the auditor.
|
||||
func (m *SecurityMonitor) AttachToAuditor() func(AuditEvent) {
|
||||
originalLogEvent := m.auditor.LogEvent
|
||||
|
||||
// Create a wrapper function that processes events and then calls the original
|
||||
return func(event AuditEvent) {
|
||||
// Process the event for monitoring
|
||||
m.ProcessEvent(event)
|
||||
|
||||
// Call the original LogEvent function
|
||||
originalLogEvent(event)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user