diff --git a/firewalld.sh b/firewalld.sh index 8629809..1316ccf 100644 --- a/firewalld.sh +++ b/firewalld.sh @@ -2,8 +2,12 @@ # ========================================== # INTERACTIVE FIREWALL CONFIGURATOR FOR SAP B1 +# (With Save/Load State) # ========================================== +# Configuration File +CONFIG_FILE="./firewall_state.conf" + # Colors for formatting RED='\033[0;31m' GREEN='\033[0;32m' @@ -14,7 +18,6 @@ NC='\033[0m' # No Color # ========================================== # SERVICE DEFINITIONS # ========================================== -# Format: "Service Name" "Ports (space separated)" declare -a SVC_NAMES declare -a SVC_PORTS @@ -59,14 +62,43 @@ print_header() { echo "" } +save_config() { + echo "# SAP B1 Firewall State - Do not edit manually unless you know what you are doing" > "$CONFIG_FILE" + for i in "${!SVC_NAMES[@]}"; do + # Use simple variable assignment format + echo "SAVED_DECISION[$i]=\"${CONFIG_DECISION[$i]}\"" >> "$CONFIG_FILE" + echo "SAVED_IPS[$i]=\"${CONFIG_IPS[$i]}\"" >> "$CONFIG_FILE" + done + echo "Config state saved to $CONFIG_FILE" +} + +load_config() { + if [ -f "$CONFIG_FILE" ]; then + echo -e "${GREEN}Found saved configuration file.${NC}" + source "$CONFIG_FILE" + # Map SAVED variables to current CONFIG variables + for i in "${!SVC_NAMES[@]}"; do + CONFIG_DECISION[$i]="${SAVED_DECISION[$i]}" + CONFIG_IPS[$i]="${SAVED_IPS[$i]}" + done + return 0 + else + return 1 + fi +} + # ========================================== -# INITIAL SETUP QUESTIONS +# INITIAL SETUP # ========================================== print_header + +# 1. Flush Question (First) echo -e "${YELLOW}Existing Configuration:${NC}" echo "Do you want to FLUSH (remove) all currently active firewall rules before starting?" echo "This ensures a clean slate. (Only affects Runtime, not Permanent config)" -read -p "Flush all current rules? (y/n): " flush_choice +read -p "Flush all current rules? [Y/n]: " flush_choice +flush_choice=${flush_choice:-Y} # Default to Yes + if [[ "$flush_choice" =~ ^[Yy]$ ]]; then DO_FLUSH=true echo -e "-> ${RED}Will flush all rules (Clean Slate).${NC}" @@ -76,6 +108,17 @@ fi echo "" sleep 1 +# 2. Load Configuration (Second) +HAS_CONFIG=false +if load_config; then + HAS_CONFIG=true + echo "Previous settings loaded. You can press ENTER to accept defaults during selection." +else + echo "No previous configuration found. Starting fresh." +fi +echo "" +sleep 1 + # ========================================== # CONFIGURATION LOOP # ========================================== @@ -89,6 +132,17 @@ for i in "${!SVC_NAMES[@]}"; do NAME="${SVC_NAMES[$i]}" PORTS="${SVC_PORTS[$i]}" + # Get previous setting if available + PREV_DECISION="${CONFIG_DECISION[$i]}" + PREV_IPS="${CONFIG_IPS[$i]}" + + # Determine default option number for UI + DEFAULT_OPT="" + DEFAULT_TXT="" + if [[ "$PREV_DECISION" == "ALL" ]]; then DEFAULT_OPT="1"; DEFAULT_TXT="[Default: 1 - Public]"; fi + if [[ "$PREV_DECISION" == "IP" ]]; then DEFAULT_OPT="2"; DEFAULT_TXT="[Default: 2 - Restricted]"; fi + if [[ "$PREV_DECISION" == "SKIP" ]]; then DEFAULT_OPT="3"; DEFAULT_TXT="[Default: 3 - Skip]"; fi + echo -e "--------------------------------------------------" echo -e "Configuring Service: ${GREEN}$NAME${NC}" echo -e "Ports: ${YELLOW}$PORTS${NC}" @@ -98,7 +152,13 @@ for i in "${!SVC_NAMES[@]}"; do echo "3) Skip / Block (Do not open)" while true; do - read -p "Select option (1-3): " choice + read -p "Select option (1-3) $DEFAULT_TXT: " choice + + # Handle Enter key (Default) + if [[ -z "$choice" && -n "$DEFAULT_OPT" ]]; then + choice=$DEFAULT_OPT + fi + case $choice in 1) CONFIG_DECISION[$i]="ALL" @@ -110,8 +170,19 @@ for i in "${!SVC_NAMES[@]}"; do CONFIG_DECISION[$i]="IP" echo "" echo -e "Enter IPs or Subnets separated by spaces or commas." - echo -e "Example: ${CYAN}192.168.1.10, 192.168.1.20${NC}" - read -p "IPs: " ip_input + + # Show previous IPs as default if they exist + if [[ -n "$PREV_IPS" ]]; then + echo -e "Current Saved IPs: ${CYAN}$PREV_IPS${NC}" + read -p "IPs [Press Enter to keep current]: " ip_input + if [[ -z "$ip_input" ]]; then + ip_input="$PREV_IPS" + fi + else + echo -e "Example: ${CYAN}192.168.1.10, 192.168.1.20${NC}" + read -p "IPs: " ip_input + fi + # Replace commas with spaces to sanitize CONFIG_IPS[$i]="${ip_input//,/ }" echo -e "-> Selected: ${GREEN}Restricted to ${CONFIG_IPS[$i]}${NC}" @@ -167,7 +238,9 @@ else fi echo "" -read -p "Do you want to apply these changes now? (y/n): " confirm +read -p "Do you want to SAVE config and APPLY changes now? [Y/n]: " confirm +confirm=${confirm:-Y} # Default to Yes + if [[ ! "$confirm" =~ ^[Yy]$ ]]; then echo "Aborted." exit 0 @@ -177,6 +250,9 @@ fi # EXECUTION # ========================================== echo "" +echo "Saving configuration to $CONFIG_FILE..." +save_config + echo "Applying configurations (RUNTIME ONLY)..." # 1. Flush or Safety Cleanup @@ -191,7 +267,6 @@ if [ "$DO_FLUSH" = true ]; then firewall-cmd --remove-port="$port" >/dev/null 2>&1 done # Flush Rich Rules - # Reading line by line to handle spaces within rules firewall-cmd --list-rich-rules | while read -r rule; do if [ -n "$rule" ]; then firewall-cmd --remove-rich-rule="$rule" >/dev/null 2>&1 @@ -201,7 +276,6 @@ else # Only remove specific conflicting rules if not flushing everything echo "-> Cleaning up insecure rules..." firewall-cmd --remove-port=0-65535/tcp >/dev/null 2>&1 - # Remove standard SSH service so we can apply precise rules firewall-cmd --remove-service=ssh >/dev/null 2>&1 firewall-cmd --remove-port=22/tcp >/dev/null 2>&1 fi @@ -226,9 +300,7 @@ for i in "${!SVC_NAMES[@]}"; do read -ra IP_ARR <<< "${CONFIG_IPS[$i]}" for ip in "${IP_ARR[@]}"; do - # Sanity check for empty strings if [[ -z "$ip" ]]; then continue; fi - for port in "${PORT_ARR[@]}"; do echo " Allowing $ip access to port $port..." firewall-cmd --add-rich-rule="rule family='ipv4' source address='$ip' port port='$port' protocol='tcp' accept" >/dev/null @@ -254,7 +326,9 @@ if read -t 15 -p "Waiting for confirmation... "; then echo "" echo -e "${GREEN}Connection confirmed!${NC}" echo "" - read -p "Do you want to save these rules PERMANENTLY now? (y/n): " save_choice + read -p "Do you want to save these rules PERMANENTLY now? [Y/n]: " save_choice + save_choice=${save_choice:-Y} # Default to Yes + if [[ "$save_choice" =~ ^[Yy]$ ]]; then echo "Saving to permanent configuration..." firewall-cmd --runtime-to-permanent