Bring script headers onto the template and close safeguard gaps
Headers claimed protections the code never had, and several destructive paths had no guard against a collapsed config value.
This commit is contained in:
@@ -21,6 +21,25 @@
|
||||
# No-op when FALLBACK_ENABLED=false or CONF_SYNC_ENABLED=false.
|
||||
#
|
||||
# ==============================================================================================
|
||||
# OPERATIONAL MODEL
|
||||
# ==============================================================================================
|
||||
#
|
||||
# One decision, driven entirely by remote reachability:
|
||||
#
|
||||
# 1. Gates
|
||||
# → PARTNERSHIP_ENABLED, FALLBACK_ENABLED, CONF_SYNC_ENABLED, REMOTE_ID
|
||||
# → any gate closed means exit 0, no work, no output
|
||||
#
|
||||
# 2. ping_remote
|
||||
# REACHABLE → remove $PERSISTENT_CONF_CACHE if it exists, exit
|
||||
# UNREACHABLE → refresh the backup from the RAM cache
|
||||
#
|
||||
# 3. Refresh (remote offline only)
|
||||
# → copy every host*.conf from the RAM cache except this host's own
|
||||
# → own conf is excluded: it is already on disk, the backup exists
|
||||
# solely to survive a reboot without the partner's vars
|
||||
#
|
||||
# ==============================================================================================
|
||||
# DESIGN PRINCIPLES
|
||||
# ==============================================================================================
|
||||
#
|
||||
@@ -38,11 +57,70 @@
|
||||
# OPERATIONAL SAFEGUARDS
|
||||
# ==============================================================================================
|
||||
#
|
||||
# require_partnership — exits early if PARTNERSHIP_ENABLED=false
|
||||
# FALLBACK_ENABLED gate — exits if fallback is disabled
|
||||
# CONF_SYNC_ENABLED gate — exits if conf sync is disabled
|
||||
# REMOTE_ID presence check — exits if partner identity is unset
|
||||
# --dry-run mode — shows what would happen without touching the backup
|
||||
# Root Enforcement
|
||||
# Writes to and removes $PERSISTENT_CONF_CACHE, which lives under the plugin
|
||||
# directory and is not user-writable.
|
||||
#
|
||||
# Lock Acquisition
|
||||
# acquire_lock() prevents concurrent execution. Without it a slow run can still
|
||||
# be copying confs into the backup while the next run, seeing the remote back
|
||||
# online, rm -rf's the directory out from under it.
|
||||
#
|
||||
# Cache Path Sanity Guard
|
||||
# PERSISTENT_CONF_CACHE is validated as an absolute path at least three levels
|
||||
# deep before any rm -rf. It is built from ${SCRIPTS_DIR} — if that is ever
|
||||
# unset the path collapses toward the filesystem root, and this script would
|
||||
# otherwise recursively delete whatever it collapsed to.
|
||||
#
|
||||
# Partnership Gate
|
||||
# require_partnership() exits early if PARTNERSHIP_ENABLED=false.
|
||||
#
|
||||
# FALLBACK_ENABLED / CONF_SYNC_ENABLED Gates
|
||||
# Exits cleanly if either is disabled — the backup only has meaning when
|
||||
# fallback can actually consume it.
|
||||
#
|
||||
# REMOTE_ID Presence Check
|
||||
# Exits if partner identity is unset. Without a partner there is nothing to
|
||||
# back up and the own-conf exclusion below could not be applied correctly.
|
||||
#
|
||||
# Own-Conf Exclusion
|
||||
# This host's own conf is never written into the partner backup. Restoring it
|
||||
# later would overwrite live local config with a stale copy.
|
||||
#
|
||||
# Dry Run Support
|
||||
# --dry-run reports every removal and copy without touching the backup.
|
||||
#
|
||||
# ==============================================================================================
|
||||
# CONFIGURATION
|
||||
# ==============================================================================================
|
||||
#
|
||||
# master.conf
|
||||
#
|
||||
# PERSISTENT_CONF_CACHE
|
||||
# Destination for the partner conf backup. Must survive a reboot, so it
|
||||
# lives under ${SCRIPTS_DIR}, not in /tmp.
|
||||
#
|
||||
# FALLBACK_ENABLED
|
||||
# Master fallback toggle. Backup is pointless when fallback cannot run.
|
||||
#
|
||||
# CONF_SYNC_ENABLED
|
||||
# Conf sync toggle. When off, no RAM cache is being maintained to back up.
|
||||
#
|
||||
# PARTNERSHIP_ENABLED
|
||||
# Checked via require_partnership().
|
||||
#
|
||||
# ==============================================================================================
|
||||
# RUNTIME MODES
|
||||
# ==============================================================================================
|
||||
#
|
||||
# conf_cache_watchdog.sh
|
||||
# Refresh or remove the persistent partner conf backup based on remote state
|
||||
#
|
||||
# conf_cache_watchdog.sh --dry-run
|
||||
# Report what would be written or removed without changing the backup
|
||||
#
|
||||
# conf_cache_watchdog.sh --log
|
||||
# Verbose per-file output
|
||||
#
|
||||
# ==============================================================================================
|
||||
|
||||
@@ -50,6 +128,17 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
source "$SCRIPT_DIR/../../load_config.sh"
|
||||
|
||||
parse_args "$@"
|
||||
|
||||
# ==============================================================================================
|
||||
# ━━━ Setup ━━━
|
||||
# ==============================================================================================
|
||||
if [[ "$EUID" -ne 0 ]]; then
|
||||
error "Must be run as root"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
acquire_lock
|
||||
|
||||
detect_hosts
|
||||
require_partnership
|
||||
|
||||
@@ -58,7 +147,19 @@ require_partnership
|
||||
[[ -z "${REMOTE_ID:-}" ]] && exit 0
|
||||
|
||||
RAM_CACHE="/tmp/.cache/vv/d"
|
||||
SAVE_DIR="$PERSISTENT_CONF_CACHE"
|
||||
SAVE_DIR="${PERSISTENT_CONF_CACHE:-}"
|
||||
|
||||
# SAVE_DIR is rm -rf'd below and is built from ${SCRIPTS_DIR}. If that is ever unset the
|
||||
# path collapses toward / — require an absolute path at least three levels deep so a
|
||||
# collapsed or empty value can never name a system directory.
|
||||
_slashes="${SAVE_DIR//[^\/]/}"
|
||||
if [[ -z "$SAVE_DIR" || "$SAVE_DIR" != /* || "${#_slashes}" -lt 3 ]]; then
|
||||
error "PERSISTENT_CONF_CACHE is unset or unsafe ('${SAVE_DIR:-unset}') — refusing to manage conf backup"
|
||||
notify "conf_cache_watchdog aborted on $(hostname) — PERSISTENT_CONF_CACHE is '${SAVE_DIR:-unset}'" \
|
||||
"Conf Cache Watchdog" "warning"
|
||||
exit 1
|
||||
fi
|
||||
unset _slashes
|
||||
|
||||
if ping_remote; then
|
||||
if [[ -d "$SAVE_DIR" ]]; then
|
||||
|
||||
Reference in New Issue
Block a user