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
73 lines
1.6 KiB
Go
73 lines
1.6 KiB
Go
package security
|
|
|
|
import (
|
|
"fmt"
|
|
"path/filepath"
|
|
"strings"
|
|
)
|
|
|
|
// CleanPath sanitizes a file path to prevent path traversal attacks
|
|
func CleanPath(path string) (string, error) {
|
|
if path == "" {
|
|
return "", fmt.Errorf("path cannot be empty")
|
|
}
|
|
|
|
// Clean the path (removes .., ., //)
|
|
cleaned := filepath.Clean(path)
|
|
|
|
// Detect path traversal attempts
|
|
if strings.Contains(cleaned, "..") {
|
|
return "", fmt.Errorf("path traversal detected: %s", path)
|
|
}
|
|
|
|
return cleaned, nil
|
|
}
|
|
|
|
// ValidateBackupPath ensures backup path is safe
|
|
func ValidateBackupPath(path string) (string, error) {
|
|
cleaned, err := CleanPath(path)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
// Convert to absolute path
|
|
absPath, err := filepath.Abs(cleaned)
|
|
if err != nil {
|
|
return "", fmt.Errorf("failed to get absolute path: %w", err)
|
|
}
|
|
|
|
return absPath, nil
|
|
}
|
|
|
|
// ValidateArchivePath validates an archive file path
|
|
func ValidateArchivePath(path string) (string, error) {
|
|
cleaned, err := CleanPath(path)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
// Must have a valid archive extension
|
|
ext := strings.ToLower(filepath.Ext(cleaned))
|
|
validExtensions := []string{".dump", ".sql", ".gz", ".tar"}
|
|
|
|
valid := false
|
|
for _, validExt := range validExtensions {
|
|
if strings.HasSuffix(cleaned, validExt) {
|
|
valid = true
|
|
break
|
|
}
|
|
}
|
|
|
|
if !valid {
|
|
return "", fmt.Errorf("invalid archive extension: %s (must be .dump, .sql, .gz, or .tar)", ext)
|
|
}
|
|
|
|
// Convert to absolute path
|
|
absPath, err := filepath.Abs(cleaned)
|
|
if err != nil {
|
|
return "", fmt.Errorf("failed to get absolute path: %w", err)
|
|
}
|
|
|
|
return absPath, nil
|
|
}
|