commit 8dcad1c178b4d9d35a0f8298565c5b08f5cbd358 Author: Tilman Kranz Date: Sun Nov 21 04:30:06 2021 +0100 initial commmit diff --git a/nft-edit-ruleset b/nft-edit-ruleset new file mode 100755 index 0000000..e5bac87 --- /dev/null +++ b/nft-edit-ruleset @@ -0,0 +1,155 @@ +#!/bin/bash +# summary: Interactively edit the current nftables ruleset. +# author: Tilman Kranz +# authoremail: tilt@linuxfoo.de +# license: MIT License (https://opensource.org/licenses/MIT) + +## +# Functions + +cleanup() { + ! "$timeout" && test -n "$tmp_old" && rm -f "$tmp_old" + test -n "$tmp" && rm -f "$tmp" +} + +at_int() { + cleanup + exit 1 +} + +at_exit() { + cleanup +} + +set_timeout() { + local ruleset=$1 + local seconds=$2 + + systemd-run \ + --description="Reverting nftables ruleset changes by $0 (PID=$$)" \ + --on-active="$seconds" \ + --timer-property=AccuracySec=100ms \ + --quiet \ + bash -c "nft -f '$ruleset' ; rm -f '$ruleset'" +} + +## +# Arguments + +yes=false +fail=false +timeout=false + +while true ; do + case "$1" in + -h|--help) + cat << EOF +Usage: $0 [--yes] [--fail] [--timeout NUM] +Description: + Interactively edit the current nftables ruleset using the editor specified + by environment variable EDITOR (defaulting to vim). Optionally, revert + changes after a timeout given in seconds. +Options: + - \`-f\`, \`--fail\`: Exit unsuccessfully if changes fail to apply. + - \`-h\`, \`--help\`: Display this message and exit. + - \`-t NUM\`, \`--timeout NUM\`: Revert changes after NUM seconds. + - \`-y\`, \`--yes\`: No confirmation before applying changes. +EOF + exit 0 + ;; + -f|--fail) + fail=true + ;; + -y|--yes) + yes=true + ;; + -t|--timeout) + if test "$#" -gt 0 ; then + shift 1 + timeout=true + timeout_secs=$1 + else + echo "ERROR: Missing argument for option \`--timeout\`, aborted." + exit 1 + fi + ;; + esac + + if test "$#" -gt 0 ; then + shift 1 + else + break + fi +done + +## +# Main Program + +if ! test -t ; then + echo "ERROR: Not connected to a terminal; aborted." + exit 1 +fi + +tmp_old=$(mktemp) +tmp=$(mktemp) + +trap at_int INT +trap at_exit EXIT + +printf 'flush ruleset\n\n' > "$tmp" + +nft list ruleset >> "$tmp" + +cat "$tmp" > "$tmp_old" + +while true ; do + editor=${EDITOR:-vim} + + "$editor" "$tmp" + + if diff "$tmp_old" "$tmp" ; then + echo "No changes." + exit 0 + else + if ! "$yes" ; then + read -p "Apply these changes? (Y|n) " -r answer + + case "$answer" in + ''|y|Y) + : + ;; + *) + echo "Aborting (user request)." + exit 1 + ;; + esac + fi + + if ! nft -c -f "$tmp" ; then + if "$fail" ; then + exit 1 + else + read -p "Errors in changes detected (Ctrl-c to abort, ENTER to continue editing)" -r answer + fi + elif ! nft -f "$tmp" ; then + if "$fail" ; then + exit 1 + else + read -p "Errors when applying changes (Ctrl-c to abort, ENTER to continue editing)" -r answer + fi + else + set_timeout "$tmp_old" "$timeout_secs" + fi + + echo "Changes applied successfully." + + if "$timeout" ; then + exit 0 + fi + fi +done + +## +# Exit Codes +# - 0: Success: No changes to apply or changes applied successfully. +# - 1: Error: Usage error or failed or aborted changes.