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
This commit is contained in:
@@ -9,18 +9,18 @@ import (
|
||||
|
||||
// AuditEvent represents an auditable event
|
||||
type AuditEvent struct {
|
||||
Timestamp time.Time
|
||||
User string
|
||||
Action string
|
||||
Resource string
|
||||
Result string
|
||||
Details map[string]interface{}
|
||||
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
|
||||
log logger.Logger
|
||||
enabled bool
|
||||
}
|
||||
|
||||
// NewAuditLogger creates a new audit logger
|
||||
|
||||
@@ -42,7 +42,7 @@ func VerifyChecksum(path string, expectedChecksum string) error {
|
||||
func SaveChecksum(archivePath string, checksum string) error {
|
||||
checksumPath := archivePath + ".sha256"
|
||||
content := fmt.Sprintf("%s %s\n", checksum, archivePath)
|
||||
|
||||
|
||||
if err := os.WriteFile(checksumPath, []byte(content), 0644); err != nil {
|
||||
return fmt.Errorf("failed to save checksum: %w", err)
|
||||
}
|
||||
@@ -53,7 +53,7 @@ func SaveChecksum(archivePath string, checksum string) error {
|
||||
// LoadChecksum loads checksum from a .sha256 file
|
||||
func LoadChecksum(archivePath string) (string, error) {
|
||||
checksumPath := archivePath + ".sha256"
|
||||
|
||||
|
||||
data, err := os.ReadFile(checksumPath)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to read checksum file: %w", err)
|
||||
|
||||
@@ -49,7 +49,7 @@ func ValidateArchivePath(path string) (string, error) {
|
||||
// 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) {
|
||||
|
||||
@@ -23,20 +23,20 @@ func NewPrivilegeChecker(log logger.Logger) *PrivilegeChecker {
|
||||
// CheckAndWarn checks if running with elevated privileges and warns
|
||||
func (pc *PrivilegeChecker) CheckAndWarn(allowRoot bool) error {
|
||||
isRoot, user := pc.isRunningAsRoot()
|
||||
|
||||
|
||||
if isRoot {
|
||||
pc.log.Warn("⚠️ Running with elevated privileges (root/Administrator)")
|
||||
pc.log.Warn("Security recommendation: Create a dedicated backup user with minimal privileges")
|
||||
|
||||
|
||||
if !allowRoot {
|
||||
return fmt.Errorf("running as root is not recommended, use --allow-root to override")
|
||||
}
|
||||
|
||||
|
||||
pc.log.Warn("Proceeding with root privileges (--allow-root specified)")
|
||||
} else {
|
||||
pc.log.Debug("Running as non-privileged user", "user", user)
|
||||
}
|
||||
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ func (pc *PrivilegeChecker) isRunningAsRoot() (bool, string) {
|
||||
func (pc *PrivilegeChecker) isUnixRoot() (bool, string) {
|
||||
uid := os.Getuid()
|
||||
user := GetCurrentUser()
|
||||
|
||||
|
||||
isRoot := uid == 0 || user == "root"
|
||||
return isRoot, user
|
||||
}
|
||||
@@ -62,10 +62,10 @@ func (pc *PrivilegeChecker) isWindowsAdmin() (bool, string) {
|
||||
// Check if running as Administrator on Windows
|
||||
// This is a simplified check - full implementation would use Windows API
|
||||
user := GetCurrentUser()
|
||||
|
||||
|
||||
// Common admin user patterns on Windows
|
||||
isAdmin := user == "Administrator" || user == "SYSTEM"
|
||||
|
||||
|
||||
return isAdmin, user
|
||||
}
|
||||
|
||||
@@ -89,11 +89,11 @@ func (pc *PrivilegeChecker) GetSecurityRecommendations() []string {
|
||||
"Regularly rotate database passwords",
|
||||
"Monitor audit logs for unauthorized access attempts",
|
||||
}
|
||||
|
||||
|
||||
if runtime.GOOS != "windows" {
|
||||
recommendations = append(recommendations,
|
||||
fmt.Sprintf("Run as non-root user: sudo -u %s dbbackup ...", pc.GetRecommendedUser()))
|
||||
}
|
||||
|
||||
|
||||
return recommendations
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// go:build !linux
|
||||
//go:build !linux
|
||||
// +build !linux
|
||||
|
||||
package security
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//go:build !windows
|
||||
// +build !windows
|
||||
|
||||
package security
|
||||
@@ -19,7 +20,7 @@ func (rc *ResourceChecker) checkPlatformLimits() (*ResourceLimits, error) {
|
||||
if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rLimit); err == nil {
|
||||
limits.MaxOpenFiles = uint64(rLimit.Cur)
|
||||
rc.log.Debug("Resource limit: max open files", "limit", rLimit.Cur, "max", rLimit.Max)
|
||||
|
||||
|
||||
if rLimit.Cur < 1024 {
|
||||
rc.log.Warn("⚠️ Low file descriptor limit detected",
|
||||
"current", rLimit.Cur,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package security
|
||||
@@ -23,5 +24,3 @@ func (rc *ResourceChecker) checkPlatformLimits() (*ResourceLimits, error) {
|
||||
|
||||
return limits, nil
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -46,13 +46,13 @@ func (rp *RetentionPolicy) CleanupOldBackups(backupDir string) (int, int64, erro
|
||||
}
|
||||
|
||||
if len(archives) <= rp.MinBackups {
|
||||
rp.log.Debug("Keeping all backups (below minimum threshold)",
|
||||
rp.log.Debug("Keeping all backups (below minimum threshold)",
|
||||
"count", len(archives), "min_backups", rp.MinBackups)
|
||||
return 0, 0, nil
|
||||
}
|
||||
|
||||
cutoffTime := time.Now().AddDate(0, 0, -rp.RetentionDays)
|
||||
|
||||
|
||||
// Sort by modification time (oldest first)
|
||||
sort.Slice(archives, func(i, j int) bool {
|
||||
return archives[i].ModTime.Before(archives[j].ModTime)
|
||||
@@ -65,14 +65,14 @@ func (rp *RetentionPolicy) CleanupOldBackups(backupDir string) (int, int64, erro
|
||||
// Keep minimum number of backups
|
||||
remaining := len(archives) - i
|
||||
if remaining <= rp.MinBackups {
|
||||
rp.log.Debug("Stopped cleanup to maintain minimum backups",
|
||||
rp.log.Debug("Stopped cleanup to maintain minimum backups",
|
||||
"remaining", remaining, "min_backups", rp.MinBackups)
|
||||
break
|
||||
}
|
||||
|
||||
// Delete if older than retention period
|
||||
if archive.ModTime.Before(cutoffTime) {
|
||||
rp.log.Info("Removing old backup",
|
||||
rp.log.Info("Removing old backup",
|
||||
"file", filepath.Base(archive.Path),
|
||||
"age_days", int(time.Since(archive.ModTime).Hours()/24),
|
||||
"size_mb", archive.Size/1024/1024)
|
||||
@@ -100,7 +100,7 @@ func (rp *RetentionPolicy) CleanupOldBackups(backupDir string) (int, int64, erro
|
||||
}
|
||||
|
||||
if deletedCount > 0 {
|
||||
rp.log.Info("Cleanup completed",
|
||||
rp.log.Info("Cleanup completed",
|
||||
"deleted_backups", deletedCount,
|
||||
"freed_space_mb", freedSpace/1024/1024,
|
||||
"retention_days", rp.RetentionDays)
|
||||
@@ -124,7 +124,7 @@ func (rp *RetentionPolicy) scanBackupArchives(backupDir string) ([]ArchiveInfo,
|
||||
}
|
||||
|
||||
name := entry.Name()
|
||||
|
||||
|
||||
// Skip non-backup files
|
||||
if !isBackupArchive(name) {
|
||||
continue
|
||||
@@ -161,7 +161,7 @@ func isBackupArchive(name string) bool {
|
||||
// extractDatabaseName extracts database name from archive filename
|
||||
func extractDatabaseName(filename string) string {
|
||||
base := filepath.Base(filename)
|
||||
|
||||
|
||||
// Remove extensions
|
||||
for {
|
||||
oldBase := base
|
||||
@@ -170,7 +170,7 @@ func extractDatabaseName(filename string) string {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Remove timestamp patterns
|
||||
if len(base) > 20 {
|
||||
// Typically: db_name_20240101_120000
|
||||
@@ -184,7 +184,7 @@ func extractDatabaseName(filename string) string {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return base
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user