Files
gniza4cp/lib/retention.sh
shuki 1f68ea1058 Security hardening, static analysis fixes, and expanded test coverage
- Fix CRITICAL: safe config parser replacing shell source, sshpass -e,
  CSRF with /dev/urandom, symlink-safe file I/O
- Fix HIGH: input validation for timestamps/accounts, path traversal
  prevention in Runner.pm, AJAX CSRF on all endpoints
- Fix MEDIUM: umask 077, chmod 700 on config dirs, Config.pm TOCTOU lock,
  rsync exit code capture bug, RSYNC_EXTRA_OPTS character validation
- ShellCheck: fix word-splitting in notify.sh, safe rm in pkgacct.sh,
  suppress cross-file SC2034 false positives
- Perl::Critic: return undef→bare return, return (sort), unpack @_,
  explicit return on void subs, rename Config::write→save
- Remove dead code: enforce_retention_all(), rsync_dry_run()
- Add require_cmd checks for rsync/ssh/hostname/gzip at startup
- Escape $hint/$tip in CGI helper functions for defense-in-depth
- Expand tests from 17→40: validate_timestamp, validate_account_name,
  _safe_source_config (including malicious input), numeric validation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 23:57:26 +02:00

41 lines
1.3 KiB
Bash

#!/usr/bin/env bash
# gniza/lib/retention.sh — Delete old snapshots beyond RETENTION_COUNT on remote
enforce_retention() {
local user="$1"
local keep="${RETENTION_COUNT:-$DEFAULT_RETENTION_COUNT}"
log_debug "Enforcing retention for $user: keeping $keep snapshots"
# Get completed snapshots sorted newest first
local snapshots; snapshots=$(list_remote_snapshots "$user")
if [[ -z "$snapshots" ]]; then
log_debug "No snapshots found for $user, nothing to prune"
return 0
fi
local count=0
local pruned=0
while IFS= read -r snap; do
((count++)) || true
if (( count > keep )); then
log_info "Pruning old snapshot for $user: $snap"
if _is_rclone_mode; then
rclone_purge "accounts/${user}/snapshots/${snap}" || {
log_warn "Failed to purge snapshot: $snap"
}
else
local snap_dir; snap_dir=$(get_snapshot_dir "$user")
remote_exec "rm -rf '$snap_dir/$snap'" || {
log_warn "Failed to prune snapshot: $snap_dir/$snap"
}
fi
((pruned++)) || true
fi
done <<< "$snapshots"
if (( pruned > 0 )); then
log_info "Pruned $pruned old snapshot(s) for $user"
fi
}