diff --git a/README.md b/README.md index a01bc90..0185e8b 100644 --- a/README.md +++ b/README.md @@ -1,28 +1,38 @@ # Usage ``` -nft-edit-ruleset [--config [CONFIG_FILE]] [--fail] [--timeout SECONDS] [--yes] +nft-edit-ruleset [--config [CONFIG_FILE]] [--fail] [--timeout SECONDS] [--yes] ``` # 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. +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 -- `-c`, `--config [CONFIG_FILE]`: On successfully applying the - changes, save ruleset to `CONFIG_FILE` (default: /etc/nftables.conf). -- `-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. +- `-c`, `--config [CONFIG_FILE]`: + If set, on successfully applying changes, save the resulting ruleset to + `CONFIG_FILE` (if `CONFIG_FILE` is not specified, it defaults to + /etc/nftables.conf). + This option is mutually exclusive with option `--timeout`. +- `-f`, `--fail`: + Exit on changes failing to apply instead of prompting the user for re-edit. +- `-h`, `--help`: + Display this message and exit. +- `-t NUM`, `--timeout NUM`: + Revert any changes NUM seconds after they have been applied. This is + implemented with a systemd timer that remains active after the program + has ended. + This option is mutually exclusive with option `--config`. +- `-y`, `--yes`: + Do not prompt for confirmation before applying changes. # Exit Codes -* 0: Success: No changes to apply or changes applied successfully. -* 1: Error: Usage error or failed or aborted changes. +- 0: Success: No changes to apply or changes applied successfully. +- 1: Error: Usage error or failed or aborted changes. # Author and License diff --git a/nft-edit-ruleset b/nft-edit-ruleset index 2d2fd39..8301bc8 100755 --- a/nft-edit-ruleset +++ b/nft-edit-ruleset @@ -43,12 +43,24 @@ set_timeout() { local ruleset=$1 local seconds=$2 - systemd-run \ - --description="Reverting nftables ruleset changes by $0 (PID=$$)" \ + if test -z "$(command -v systemd-run)" ; then + echo "ERROR: Setting undo timeout failed (systemd-run not found)" >&2 + return 1 + fi + + if systemd-run \ + --unit="nft-edit-ruleset-revert-changes" \ + --description="reverting nftables ruleset changes by $0 (PID=$$)" \ --on-active="$seconds" \ --timer-property=AccuracySec=100ms \ --quiet \ bash -c "nft -f '$ruleset' ; rm -f '$ruleset'" + then + return 0 + else + echo "ERROR: Setting undo timeout failed (already running?)" >&2 + return 1 + fi } store_config() { @@ -90,15 +102,21 @@ after a timeout given in seconds. # OPTIONS - \`-c\`, \`--config [CONFIG_FILE]\`: - On success, save ruleset to \`CONFIG_FILE\` (default: $default_config_file). + If set, on successfully applying changes, save the resulting ruleset to + \`CONFIG_FILE\` (if \`CONFIG_FILE\` is not specified, it defaults to + $default_config_file). + This option is mutually exclusive with option \`--timeout\`. - \`-f\`, \`--fail\`: - Exit unsuccessfully if changes fail to apply. + Exit on changes failing to apply instead of prompting the user for re-edit. - \`-h\`, \`--help\`: Display this message and exit. - \`-t NUM\`, \`--timeout NUM\`: - Revert changes after NUM seconds. + Revert any changes NUM seconds after they have been applied. This is + implemented with a systemd timer that remains active after the program + has ended. + This option is mutually exclusive with option \`--config\`. - \`-y\`, \`--yes\`: - No confirmation before applying changes. + Do not prompt for confirmation before applying changes. # EXIT CODES - 0: Success: No changes to apply or changes applied successfully. @@ -130,12 +148,16 @@ EOF -c|--config) config=true - if test "$#" -gt 0 && { test -w "$2" || test -w "$(dirname "$2")" ; } ; then + if \ + test "$#" -gt 0 && \ + ! [[ "$2" =~ ^- ]] && \ + { test -w "$2" || test -w "$(dirname "$2")" ; } + then shift 1 config_file=$1 elif test -z "$default_config_file" ; then echo \ - "ERROR: Option \`--config\` was used without an argument," \ + "ERROR: Option \`--config\` was used without a valid argument," \ "but no default location of a file \"nftables.conf\" could be found" \ "(use \`--config CONFIG_FILE\` to specify a location); aborted." >&2 exit 1 @@ -159,6 +181,11 @@ EOF fi done +if "$config" && "$timeout" ; then + echo "ERROR: Options \`--config\` and \`--timeout\` are mutually exclusive; aborted." >&2 + exit 1 +fi + ## # Main Program @@ -179,6 +206,8 @@ nft list ruleset >> "$tmp" cat "$tmp" > "$tmp_old" +rv=0 + while true ; do editor=${EDITOR:-vim} @@ -192,7 +221,8 @@ while true ; do echo "Stored unchanged ruleset to config_file=\"$config_file\"." else echo "ERROR: Storing unchanged ruleset to config_file=\"$config_file\" failed." >&2 - exit 1 + rv=1 + break fi fi @@ -207,36 +237,39 @@ while true ; do ;; *) echo "Aborting (user request)." - exit 1 + rv=1 + break ;; esac fi if ! nft -c -f "$tmp" ; then if "$fail" ; then - exit 1 + rv=1 + break 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 + rv=1 + break else read -p "Errors when applying changes (Ctrl-c to abort, ENTER to continue editing)" -r answer fi else - if "$timeout" ; then - set_timeout "$tmp_old" "$timeout_secs" - fi - echo "Changes applied successfully." - if "$config" ; then + if "$timeout" ; then + if ! set_timeout "$tmp_old" "$timeout_secs" ; then + rv=1 + fi + elif "$config" ; then if store_config "$tmp" "$config_file" ; then echo "Stored changed ruleset to config_file=\"$config_file\"." else echo "ERROR: Storing changed ruleset to config_file=\"$config_file\" failed." >&2 - exit 1 + rv=1 fi fi @@ -245,6 +278,8 @@ while true ; do fi done +exit $rv + ## # Exit Codes # - 0: Success: No changes to apply or changes applied successfully.