Files
dbbackup/internal/security/audit.go
A. Renz 914307ac8f ci: add golangci-lint config and fix formatting
- Add .golangci.yml with minimal linters (govet, ineffassign)
- Run gofmt -s and goimports on all files to fix formatting
- Disable fieldalignment and copylocks checks in govet
2025-12-11 17:53:28 +01:00

235 lines
4.5 KiB
Go
Executable File

package security
import (
"os"
"time"
"dbbackup/internal/logger"
)
// AuditEvent represents an auditable event
type AuditEvent struct {
Timestamp time.Time
User string
Action string
Resource string
Result string
Details map[string]interface{}
}
// AuditLogger provides audit logging functionality
type AuditLogger struct {
log logger.Logger
enabled bool
}
// NewAuditLogger creates a new audit logger
func NewAuditLogger(log logger.Logger, enabled bool) *AuditLogger {
return &AuditLogger{
log: log,
enabled: enabled,
}
}
// LogBackupStart logs backup operation start
func (a *AuditLogger) LogBackupStart(user, database, backupType string) {
if !a.enabled {
return
}
event := AuditEvent{
Timestamp: time.Now(),
User: user,
Action: "BACKUP_START",
Resource: database,
Result: "INITIATED",
Details: map[string]interface{}{
"backup_type": backupType,
},
}
a.logEvent(event)
}
// LogBackupComplete logs successful backup completion
func (a *AuditLogger) LogBackupComplete(user, database, archivePath string, sizeBytes int64) {
if !a.enabled {
return
}
event := AuditEvent{
Timestamp: time.Now(),
User: user,
Action: "BACKUP_COMPLETE",
Resource: database,
Result: "SUCCESS",
Details: map[string]interface{}{
"archive_path": archivePath,
"size_bytes": sizeBytes,
},
}
a.logEvent(event)
}
// LogBackupFailed logs backup failure
func (a *AuditLogger) LogBackupFailed(user, database string, err error) {
if !a.enabled {
return
}
event := AuditEvent{
Timestamp: time.Now(),
User: user,
Action: "BACKUP_FAILED",
Resource: database,
Result: "FAILURE",
Details: map[string]interface{}{
"error": err.Error(),
},
}
a.logEvent(event)
}
// LogRestoreStart logs restore operation start
func (a *AuditLogger) LogRestoreStart(user, database, archivePath string) {
if !a.enabled {
return
}
event := AuditEvent{
Timestamp: time.Now(),
User: user,
Action: "RESTORE_START",
Resource: database,
Result: "INITIATED",
Details: map[string]interface{}{
"archive_path": archivePath,
},
}
a.logEvent(event)
}
// LogRestoreComplete logs successful restore completion
func (a *AuditLogger) LogRestoreComplete(user, database string, duration time.Duration) {
if !a.enabled {
return
}
event := AuditEvent{
Timestamp: time.Now(),
User: user,
Action: "RESTORE_COMPLETE",
Resource: database,
Result: "SUCCESS",
Details: map[string]interface{}{
"duration_seconds": duration.Seconds(),
},
}
a.logEvent(event)
}
// LogRestoreFailed logs restore failure
func (a *AuditLogger) LogRestoreFailed(user, database string, err error) {
if !a.enabled {
return
}
event := AuditEvent{
Timestamp: time.Now(),
User: user,
Action: "RESTORE_FAILED",
Resource: database,
Result: "FAILURE",
Details: map[string]interface{}{
"error": err.Error(),
},
}
a.logEvent(event)
}
// LogConfigChange logs configuration changes
func (a *AuditLogger) LogConfigChange(user, setting, oldValue, newValue string) {
if !a.enabled {
return
}
event := AuditEvent{
Timestamp: time.Now(),
User: user,
Action: "CONFIG_CHANGE",
Resource: setting,
Result: "SUCCESS",
Details: map[string]interface{}{
"old_value": oldValue,
"new_value": newValue,
},
}
a.logEvent(event)
}
// LogConnectionAttempt logs database connection attempts
func (a *AuditLogger) LogConnectionAttempt(user, host string, success bool, err error) {
if !a.enabled {
return
}
result := "SUCCESS"
details := map[string]interface{}{
"host": host,
}
if !success {
result = "FAILURE"
if err != nil {
details["error"] = err.Error()
}
}
event := AuditEvent{
Timestamp: time.Now(),
User: user,
Action: "DB_CONNECTION",
Resource: host,
Result: result,
Details: details,
}
a.logEvent(event)
}
// logEvent writes the audit event to log
func (a *AuditLogger) logEvent(event AuditEvent) {
fields := map[string]interface{}{
"audit": true,
"timestamp": event.Timestamp.Format(time.RFC3339),
"user": event.User,
"action": event.Action,
"resource": event.Resource,
"result": event.Result,
}
// Merge event details
for k, v := range event.Details {
fields[k] = v
}
a.log.WithFields(fields).Info("AUDIT")
}
// GetCurrentUser returns the current system user
func GetCurrentUser() string {
if user := os.Getenv("USER"); user != "" {
return user
}
if user := os.Getenv("USERNAME"); user != "" {
return user
}
return "unknown"
}