Skip to main content

Script Any Arbitrary Backend

The "script" backend type is simply a script the agent can execute that takes a fixed set of arguments.

  1. Action: add (to grant access), del(to revoke access) or flush(to empty/reset the whole ACL);
  2. ACL (or "set name"): the name of the ACL for validation, or for example a AWS security group ID;
  3. IP address: the IP address detected by the server for the user's session. This is not provided for a flush action.

If your backend does not require an ACL name or equivalent, allocate and discard the value.

The agent monitors the script for its exit status. A zero (0) exit code is considered successful; a non-zero exit code counts as an error and this is reflected on the end user's Knocknoc dashboard.

Scripts work best if they are idempotent, that is to say they can be called multiple times with the same arguments and the end result is the same. For example, even if the script is called more than once to grant a single IP, avoid raising an error; just ensure the grant has been applied to your system correctly. Similarly for a del/revocation, the script should be able to be called multiple times to ensure a given IP is not present in the specified ACL.

Example: ipsetter.sh

This script is bundled with the Knocknoc agent. It demonstrates reading the 1st, 2nd and 3rd arguments to get the action, ACL name and IP address respectively. It's always a good idea to validate the inputs.

#!/bin/bash
# Wrapper script to allow safe parsing of an ipset command line from sudo
# sudo is run in this scrip itself, so you need to enable the ipset command in sudoers
# like so:
# make a file in /etc/sudoers.d/knocknoc-agent with this contents:
# knocknoc-agent ALL=(ALL:ALL) NOPASSWD: /usr/sbin/ipset *
# 
# This will allow this script to run the ipset command as root.


set -e -o pipefail

# Validate IP address
function validate_ip() {
    local ip=$1
    if [[ $ip =~ ^[0-9]{1,3}(\.[0-9]{1,3}){3}$ ]]; then
        return 0
    else
        echo "Invalid IP address"
        exit 1
    fi
}

# Validate setname
function validate_setname() {
    local setname=$1
    if [[ $setname =~ ^[A-Za-z0-9_]+$ ]]; then
        return 0
    else
        echo "Invalid setname"
        exit 1
    fi
}

# Validate operation
function validate_op() {
    local op=$1
    if [[ $op =~ ^(add|del|flush)$ ]]; then
        return 0
    else
        echo "Invalid operation"
        exit 1
    fi
}

# Validate and assign operation
validate_op "$1"
op="$1"

# Validate and assign setname
validate_setname "$2"
setname="$2"

# Execute ipset command
if [[ "$op" = "flush" ]]; then
    exec sudo /usr/sbin/ipset "$op" "$setname"
else
    # Validate and assign IP address
    validate_ip "$3"
    ip="$3"
    exec sudo /usr/sbin/ipset "$op" "$setname" "$ip"
fi

This structure empowers you to use Knocknoc as a unified platform for managing IP-based access to practically any scriptable system.