testsAndMisc/linux_configuration/scripts/periodic_background/hosts/guard/enforce-nsswitch.sh
Krzysztof kuhy Rudnicki db6276b3ff refactor(linux_configuration): move remaining dirs + scripts/ to meta/
- Move fresh-install/ → scripts/single_use/fresh-install/
- Move hosts/ → scripts/periodic_background/hosts/
- Move i3-configuration/ → scripts/periodic_background/i3-configuration/
- Delete linux_configuration/LaTeX/, nix-poc/, report/ (dead dirs)
- Move repo-root scripts/ → meta/scripts/
- Update root .pre-commit-config.yaml: scripts/ → meta/scripts/ (9 entries)
- Update run.sh ARTIFACT_INIT_SCRIPT to meta/scripts/
- Update fresh-install/main.sh: hosts/install.sh + i3-configuration/install.sh paths
- Update check_python_location.sh: add meta/scripts/ to exception list
- Fix midnight flakiness in test_recent_workout_returns_true: use timezone-aware
  local noon instead of now-1h to avoid SQL date() boundary issues
2026-05-15 00:53:01 +02:00

110 lines
3.6 KiB
Bash
Executable File

#!/bin/bash
# Template guard script to enforce canonical /etc/nsswitch.conf
# Ensures "hosts:" line always contains "files" before "dns"
# This prevents bypassing /etc/hosts by removing "files" from nsswitch.conf
# Installed to /usr/local/sbin/enforce-nsswitch.sh by setup_hosts_guard.sh
set -euo pipefail
CANONICAL_SOURCE="/usr/local/share/locked-nsswitch.conf"
TARGET="/etc/nsswitch.conf"
LOG_FILE="/var/log/nsswitch-guard.log"
log() {
printf '%s - %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$*" | tee -a "$LOG_FILE" >&2
}
# Function to validate that "hosts:" line has correct format
# Must contain "files" before "dns" (or "dns" not present)
validate_hosts_line() {
local line="$1"
# Check if "files" is present
if ! echo "$line" | grep -qw "files"; then
return 1
fi
# If dns is present, files must come before it
if echo "$line" | grep -qw "dns"; then
local files_pos dns_pos
files_pos=$(echo "$line" | grep -bo '\bfiles\b' | head -1 | cut -d: -f1)
dns_pos=$(echo "$line" | grep -bo '\bdns\b' | head -1 | cut -d: -f1)
if [[ -n "$files_pos" && -n "$dns_pos" && "$files_pos" -gt "$dns_pos" ]]; then
return 1
fi
fi
return 0
}
# Check current nsswitch.conf hosts line
current_hosts_line=$(grep '^hosts:' "$TARGET" 2>/dev/null || echo "")
if [[ -z "$current_hosts_line" ]]; then
log "CRITICAL: No 'hosts:' line found in $TARGET - restoring from canonical"
if [[ -f "$CANONICAL_SOURCE" ]]; then
chattr -i "$TARGET" 2>/dev/null || true
cp "$CANONICAL_SOURCE" "$TARGET"
chmod 644 "$TARGET"
chattr +i "$TARGET" 2>/dev/null || log "Failed to set immutable attribute on $TARGET"
log "Restored $TARGET from canonical copy"
else
log "ERROR: Canonical source not found at $CANONICAL_SOURCE"
exit 1
fi
exit 0
fi
if ! validate_hosts_line "$current_hosts_line"; then
log "TAMPERING DETECTED: 'hosts:' line is invalid or missing 'files' before 'dns'"
log "Current line: $current_hosts_line"
if [[ -f "$CANONICAL_SOURCE" ]]; then
chattr -i "$TARGET" 2>/dev/null || true
cp "$CANONICAL_SOURCE" "$TARGET"
chmod 644 "$TARGET"
chattr +i "$TARGET" 2>/dev/null || log "Failed to set immutable attribute on $TARGET"
log "Restored $TARGET from canonical copy"
else
log "ERROR: Canonical source not found at $CANONICAL_SOURCE"
# Emergency fix: add "files" back to hosts line
chattr -i "$TARGET" 2>/dev/null || true
if grep -q '^hosts:.*dns' "$TARGET"; then
sed -i 's/^hosts:\(.*\)dns/hosts:\1files dns/' "$TARGET"
elif grep -q '^hosts:.*resolve' "$TARGET"; then
sed -i 's/^hosts:\(.*\)resolve/hosts: files\1resolve/' "$TARGET"
else
sed -i 's/^hosts:/hosts: files/' "$TARGET"
fi
chattr +i "$TARGET" 2>/dev/null || true
log "Emergency fix applied: added 'files' to hosts line"
fi
exit 0
fi
# If canonical exists, check for any drift
if [[ -f "$CANONICAL_SOURCE" ]]; then
if ! cmp -s "$CANONICAL_SOURCE" "$TARGET"; then
log "Drift detected in $TARGET (but hosts line valid) - restoring canonical"
chattr -i "$TARGET" 2>/dev/null || true
cp "$CANONICAL_SOURCE" "$TARGET"
chmod 644 "$TARGET"
chattr +i "$TARGET" 2>/dev/null || log "Failed to set immutable attribute"
log "Restored $TARGET from canonical copy"
else
log "No drift detected in $TARGET"
fi
else
log "Creating initial canonical snapshot"
mkdir -p "$(dirname "$CANONICAL_SOURCE")"
cp "$TARGET" "$CANONICAL_SOURCE"
chmod 644 "$CANONICAL_SOURCE"
chattr +i "$CANONICAL_SOURCE" 2>/dev/null || log "Failed to protect canonical copy"
fi
# Ensure immutable attribute is set
chattr -i "$TARGET" 2>/dev/null || true
chattr +i "$TARGET" 2>/dev/null || log "Failed to set immutable attribute on $TARGET"
log "nsswitch.conf enforcement complete"