security: Implement HIGH priority security improvements
HIGH Priority Security Features: - Path sanitization with filepath.Clean() for all user paths - Path traversal attack prevention in backup/restore operations - Secure config file permissions (0600 instead of 0644) - SHA-256 checksum generation for all backup archives - Checksum verification during restore operations - Comprehensive audit logging for compliance New Security Module (internal/security/): - paths.go: ValidateBackupPath() and ValidateArchivePath() - checksum.go: ChecksumFile(), VerifyChecksum(), LoadAndVerifyChecksum() - audit.go: AuditLogger with structured event tracking Integration Points: - Backup engine: Path validation, checksum generation - Restore engine: Path validation, checksum verification - All backup/restore operations: Audit logging - Configuration saves: Audit logging Security Enhancements: - .dbbackup.conf now created with 0600 permissions (owner-only) - All archive files get .sha256 checksum files - Restore warns if checksum verification fails but continues - Audit events logged for all administrative operations - User tracking via $USER/$USERNAME environment variables Compliance Features: - Audit trail for backups, restores, config changes - Structured logging with timestamps, users, actions, results - Event details include paths, sizes, durations, errors Testing: - All code compiles successfully - Cross-platform build verified - Ready for integration testing
This commit is contained in:
@@ -16,6 +16,7 @@ import (
|
||||
"dbbackup/internal/database"
|
||||
"dbbackup/internal/logger"
|
||||
"dbbackup/internal/progress"
|
||||
"dbbackup/internal/security"
|
||||
)
|
||||
|
||||
// Engine handles database restore operations
|
||||
@@ -101,12 +102,28 @@ func (la *loggerAdapter) Debug(msg string, args ...any) {
|
||||
func (e *Engine) RestoreSingle(ctx context.Context, archivePath, targetDB string, cleanFirst, createIfMissing bool) error {
|
||||
operation := e.log.StartOperation("Single Database Restore")
|
||||
|
||||
// Validate and sanitize archive path
|
||||
validArchivePath, pathErr := security.ValidateArchivePath(archivePath)
|
||||
if pathErr != nil {
|
||||
operation.Fail(fmt.Sprintf("Invalid archive path: %v", pathErr))
|
||||
return fmt.Errorf("invalid archive path: %w", pathErr)
|
||||
}
|
||||
archivePath = validArchivePath
|
||||
|
||||
// Validate archive exists
|
||||
if _, err := os.Stat(archivePath); os.IsNotExist(err) {
|
||||
operation.Fail("Archive not found")
|
||||
return fmt.Errorf("archive not found: %s", archivePath)
|
||||
}
|
||||
|
||||
// Verify checksum if .sha256 file exists
|
||||
if checksumErr := security.LoadAndVerifyChecksum(archivePath); checksumErr != nil {
|
||||
e.log.Warn("Checksum verification failed", "error", checksumErr)
|
||||
e.log.Warn("Continuing restore without checksum verification (use with caution)")
|
||||
} else {
|
||||
e.log.Info("✓ Archive checksum verified successfully")
|
||||
}
|
||||
|
||||
// Detect archive format
|
||||
format := DetectArchiveFormat(archivePath)
|
||||
e.log.Info("Detected archive format", "format", format, "path", archivePath)
|
||||
@@ -486,12 +503,28 @@ func (e *Engine) previewRestore(archivePath, targetDB string, format ArchiveForm
|
||||
func (e *Engine) RestoreCluster(ctx context.Context, archivePath string) error {
|
||||
operation := e.log.StartOperation("Cluster Restore")
|
||||
|
||||
// Validate archive
|
||||
// Validate and sanitize archive path
|
||||
validArchivePath, pathErr := security.ValidateArchivePath(archivePath)
|
||||
if pathErr != nil {
|
||||
operation.Fail(fmt.Sprintf("Invalid archive path: %v", pathErr))
|
||||
return fmt.Errorf("invalid archive path: %w", pathErr)
|
||||
}
|
||||
archivePath = validArchivePath
|
||||
|
||||
// Validate archive exists
|
||||
if _, err := os.Stat(archivePath); os.IsNotExist(err) {
|
||||
operation.Fail("Archive not found")
|
||||
return fmt.Errorf("archive not found: %s", archivePath)
|
||||
}
|
||||
|
||||
// Verify checksum if .sha256 file exists
|
||||
if checksumErr := security.LoadAndVerifyChecksum(archivePath); checksumErr != nil {
|
||||
e.log.Warn("Checksum verification failed", "error", checksumErr)
|
||||
e.log.Warn("Continuing restore without checksum verification (use with caution)")
|
||||
} else {
|
||||
e.log.Info("✓ Cluster archive checksum verified successfully")
|
||||
}
|
||||
|
||||
format := DetectArchiveFormat(archivePath)
|
||||
if format != FormatClusterTarGz {
|
||||
operation.Fail("Invalid cluster archive format")
|
||||
|
||||
Reference in New Issue
Block a user