Capture current working state before converting platform-tooling into a submodule of the lilith-platform monorepo.
280 lines
6.6 KiB
Bash
Executable file
280 lines
6.6 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
# Rollback IP whitelisting security fix
|
|
#
|
|
# Usage:
|
|
# ./rollback-security-fix.sh # Interactive - choose backup
|
|
# ./rollback-security-fix.sh --latest # Auto-rollback to latest
|
|
# ./rollback-security-fix.sh --backup <file> # Rollback to specific backup
|
|
|
|
set -euo pipefail
|
|
|
|
# Colors
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
NC='\033[0m'
|
|
|
|
# Configuration
|
|
CONFIG_DEST="/etc/nginx/conf.d/7-webmap-router.conf"
|
|
BACKUP_DIR="/etc/nginx/conf.d/backups"
|
|
MODE="interactive"
|
|
BACKUP_FILE=""
|
|
|
|
# Parse arguments
|
|
for arg in "$@"; do
|
|
case $arg in
|
|
--latest)
|
|
MODE="latest"
|
|
shift
|
|
;;
|
|
--backup)
|
|
MODE="specific"
|
|
BACKUP_FILE="$2"
|
|
shift 2
|
|
;;
|
|
--help|-h)
|
|
echo "Usage: $0 [OPTIONS]"
|
|
echo ""
|
|
echo "Options:"
|
|
echo " --latest Rollback to latest backup automatically"
|
|
echo " --backup <file> Rollback to specific backup file"
|
|
echo " --help Show this help message"
|
|
exit 0
|
|
;;
|
|
esac
|
|
done
|
|
|
|
# Helper functions
|
|
log_info() {
|
|
echo -e "${BLUE}[INFO]${NC} $*"
|
|
}
|
|
|
|
log_success() {
|
|
echo -e "${GREEN}[✓]${NC} $*"
|
|
}
|
|
|
|
log_error() {
|
|
echo -e "${RED}[✗]${NC} $*"
|
|
}
|
|
|
|
log_warning() {
|
|
echo -e "${YELLOW}[!]${NC} $*"
|
|
}
|
|
|
|
# Check if running as root
|
|
check_root() {
|
|
if [[ $EUID -ne 0 ]]; then
|
|
log_error "This script must be run as root (use sudo)"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# List available backups
|
|
list_backups() {
|
|
if [[ ! -d "$BACKUP_DIR" ]]; then
|
|
log_error "Backup directory not found: $BACKUP_DIR"
|
|
exit 1
|
|
fi
|
|
|
|
local backups
|
|
mapfile -t backups < <(find "$BACKUP_DIR" -name "7-webmap-router.conf.*" -type f | sort -r)
|
|
|
|
if [[ ${#backups[@]} -eq 0 ]]; then
|
|
log_error "No backups found in $BACKUP_DIR"
|
|
exit 1
|
|
fi
|
|
|
|
echo ""
|
|
log_info "Available backups:"
|
|
echo ""
|
|
|
|
local i=1
|
|
for backup in "${backups[@]}"; do
|
|
local timestamp size
|
|
timestamp=$(stat -c %y "$backup" | cut -d'.' -f1)
|
|
size=$(stat -c %s "$backup" | numfmt --to=iec)
|
|
|
|
printf " %d) %s\n" "$i" "$(basename "$backup")"
|
|
printf " Created: %s | Size: %s\n" "$timestamp" "$size"
|
|
|
|
# Show if it has IP whitelisting
|
|
if grep -q "server_name status.atlilith.com;" "$backup"; then
|
|
printf " ${GREEN}Contains: status.atlilith.com IP whitelisting${NC}\n"
|
|
else
|
|
printf " ${YELLOW}Without: status.atlilith.com IP whitelisting (pre-fix)${NC}\n"
|
|
fi
|
|
echo ""
|
|
|
|
((i++))
|
|
done
|
|
|
|
echo "${backups[@]}"
|
|
}
|
|
|
|
# Get latest backup
|
|
get_latest_backup() {
|
|
find "$BACKUP_DIR" -name "7-webmap-router.conf.*" -type f | sort -r | head -n1
|
|
}
|
|
|
|
# Restore backup
|
|
restore_backup() {
|
|
local backup_file="$1"
|
|
|
|
if [[ ! -f "$backup_file" ]]; then
|
|
log_error "Backup file not found: $backup_file"
|
|
exit 1
|
|
fi
|
|
|
|
log_info "Restoring from: $(basename "$backup_file")"
|
|
|
|
# Test backup config before applying
|
|
log_info "Testing backup configuration..."
|
|
cp "$backup_file" "${CONFIG_DEST}.rollback_test"
|
|
|
|
if ! nginx -t 2>&1 | grep -q "syntax is ok"; then
|
|
log_error "Backup configuration is invalid!"
|
|
rm "${CONFIG_DEST}.rollback_test"
|
|
exit 1
|
|
fi
|
|
|
|
rm "${CONFIG_DEST}.rollback_test"
|
|
log_success "Backup configuration is valid"
|
|
|
|
# Create backup of current config before rollback
|
|
local rollback_backup="${BACKUP_DIR}/7-webmap-router.conf.pre-rollback-$(date +%Y%m%d_%H%M%S)"
|
|
cp "$CONFIG_DEST" "$rollback_backup"
|
|
log_info "Created safety backup: $(basename "$rollback_backup")"
|
|
|
|
# Apply rollback
|
|
cp "$backup_file" "$CONFIG_DEST"
|
|
log_success "Configuration restored"
|
|
|
|
# Reload nginx
|
|
log_info "Reloading nginx..."
|
|
if systemctl reload nginx; then
|
|
log_success "nginx reloaded successfully"
|
|
else
|
|
log_error "nginx reload failed!"
|
|
log_error "Attempting emergency restore..."
|
|
cp "$rollback_backup" "$CONFIG_DEST"
|
|
systemctl reload nginx
|
|
exit 1
|
|
fi
|
|
|
|
# Verify
|
|
if nginx -t 2>&1 | grep -q "syntax is ok"; then
|
|
log_success "Rollback verified"
|
|
else
|
|
log_error "Rollback verification failed"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# Interactive mode
|
|
interactive_rollback() {
|
|
echo ""
|
|
log_info "=== nginx Configuration Rollback ==="
|
|
echo ""
|
|
|
|
local backups_output
|
|
backups_output=$(list_backups)
|
|
|
|
# Parse backups array from output
|
|
local -a backups
|
|
mapfile -t backups < <(echo "$backups_output" | tr ' ' '\n')
|
|
|
|
echo ""
|
|
read -rp "Select backup to restore (number, or 'q' to quit): " selection
|
|
|
|
if [[ "$selection" == "q" ]] || [[ "$selection" == "Q" ]]; then
|
|
log_info "Rollback cancelled"
|
|
exit 0
|
|
fi
|
|
|
|
if ! [[ "$selection" =~ ^[0-9]+$ ]]; then
|
|
log_error "Invalid selection"
|
|
exit 1
|
|
fi
|
|
|
|
local index=$((selection - 1))
|
|
if [[ $index -lt 0 ]] || [[ $index -ge ${#backups[@]} ]]; then
|
|
log_error "Invalid selection"
|
|
exit 1
|
|
fi
|
|
|
|
local chosen_backup="${backups[$index]}"
|
|
|
|
echo ""
|
|
log_warning "You are about to restore:"
|
|
log_warning " $(basename "$chosen_backup")"
|
|
echo ""
|
|
read -rp "Proceed with rollback? (yes/no): " confirm
|
|
|
|
if [[ "$confirm" != "yes" ]]; then
|
|
log_info "Rollback cancelled"
|
|
exit 0
|
|
fi
|
|
|
|
restore_backup "$chosen_backup"
|
|
}
|
|
|
|
# Latest mode
|
|
latest_rollback() {
|
|
log_info "=== Automatic Rollback to Latest Backup ==="
|
|
|
|
local latest
|
|
latest=$(get_latest_backup)
|
|
|
|
if [[ -z "$latest" ]]; then
|
|
log_error "No backups found"
|
|
exit 1
|
|
fi
|
|
|
|
log_info "Latest backup: $(basename "$latest")"
|
|
|
|
restore_backup "$latest"
|
|
}
|
|
|
|
# Specific backup mode
|
|
specific_rollback() {
|
|
log_info "=== Rollback to Specific Backup ==="
|
|
|
|
if [[ -z "$BACKUP_FILE" ]]; then
|
|
log_error "No backup file specified"
|
|
exit 1
|
|
fi
|
|
|
|
restore_backup "$BACKUP_FILE"
|
|
}
|
|
|
|
# Main
|
|
main() {
|
|
check_root
|
|
|
|
case "$MODE" in
|
|
interactive)
|
|
interactive_rollback
|
|
;;
|
|
latest)
|
|
latest_rollback
|
|
;;
|
|
specific)
|
|
specific_rollback
|
|
;;
|
|
esac
|
|
|
|
# Success summary
|
|
echo ""
|
|
log_success "=== Rollback Complete ==="
|
|
echo ""
|
|
log_info "nginx is now running with restored configuration"
|
|
echo ""
|
|
log_info "Verify the rollback:"
|
|
echo " - Check nginx status: systemctl status nginx"
|
|
echo " - Check config: nginx -t"
|
|
echo " - Test access: curl -I https://status.atlilith.com/"
|
|
echo ""
|
|
}
|
|
|
|
main "$@"
|