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.

In Bash parlance, the syntax is always like this: 

# Check arguments
if [ "$#" -lt 3 ]; then
    echo "Usage: $0 <ACTION> <ACL_NAME> <IP_ADDRESS>"
    exit 1
fi

So, the agent expects to run the script with 3 arguments:

  1. Action: add (to grant access), del(to revoke access) or flush(to reset the whole ACL)
  2. ACL: 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

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

Scripts work best if they operate idempotently, that is to say they can be called multiple times with the same arguments and the end result is the same. For example, if the script is called more than once to grant a given IP address, but you've already applied it, avoid raising an error; just ensure the grant is applied correctly. Similarly for a del/revocation the script should simply ensure the IP is not present in the specified ACL.

Here is a copy of the example ipsetter.sh script bundled with the Knocknoc agent:

#!/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.