Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions config/approved_targets.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Approved targets for scan/capture scripts (nmap.sh, host.sh, scanPlus.sh,
# live_network_monitor.sh). One entry per line.
#
# - Exact hostnames, IPs, or network interface names are matched as-is.
# - Glob patterns are supported, e.g. 10.0.0.*, *.internal.example.com.
# - Lines starting with # are comments.
#
# Every scan/capture run also requires AUTHORIZED_TICKET to be set to a
# change/work-order reference — this file alone does not authorize a run.
# Keep this list under change control: additions should map to an actual
# approved engagement or maintenance window, not be added ad hoc.

127.0.0.1
localhost
48 changes: 48 additions & 0 deletions lib/authorization.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#!/bin/bash
# Authorization gate for scan/capture tools. CJIS-adjacent environments
# require scanning and monitoring to be explicitly authorized, not just
# recorded after the fact — this checks a target against an approved-
# targets allowlist and requires a ticket/work-order reference before the
# caller is allowed to proceed. Depends on audit_log() (source
# lib/audit_log.sh first).

AUTH_ALLOWLIST="${AUTH_ALLOWLIST:-$REPO_ROOT/config/approved_targets.txt}"

# require_authorization <script_name> <target>
# Exits the calling script if AUTHORIZED_TICKET is unset or the target
# isn't on the allowlist. Every denial and grant is audit-logged.
require_authorization() {
local script_name="$1" target="$2"

if [ -z "${AUTHORIZED_TICKET:-}" ]; then
echo "Refusing to run: set AUTHORIZED_TICKET to the change/work-order reference authorizing this action." >&2
audit_log "$script_name" "authorization_denied" "$target" 1
exit 1
fi

if [ ! -f "$AUTH_ALLOWLIST" ]; then
echo "Refusing to run: no approved-targets allowlist found at $AUTH_ALLOWLIST." >&2
audit_log "$script_name" "authorization_denied" "$target" 1
exit 1
fi

local pattern matched=0
while IFS= read -r pattern; do
[ -z "$pattern" ] && continue
case "$pattern" in
\#*) continue ;;
esac
# shellcheck disable=SC2254 # unquoted on purpose: allowlist entries are globs
case "$target" in
$pattern) matched=1; break ;;
esac
done < "$AUTH_ALLOWLIST"

if [ "$matched" -ne 1 ]; then
echo "Refusing to run: '$target' is not on the approved-targets allowlist ($AUTH_ALLOWLIST)." >&2
audit_log "$script_name" "authorization_denied" "$target" 1
exit 1
fi

audit_log "$script_name" "authorization_granted" "${target} (ticket=${AUTHORIZED_TICKET})" 0
}
4 changes: 4 additions & 0 deletions scanPlus.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,14 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null || echo "$SCRIPT_DIR")"
# shellcheck source=/dev/null
source "$REPO_ROOT/lib/audit_log.sh"
# shellcheck source=/dev/null
source "$REPO_ROOT/lib/authorization.sh"

echo "Enter the target IP address:"
read -r target

require_authorization "scanPlus.sh" "$target"

echo "Enter the starting port number:"
read -r start

Expand Down
4 changes: 4 additions & 0 deletions src/networking-tools/host_scan/host.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null || echo "$SCRIPT_DIR")"
# shellcheck source=/dev/null
source "$REPO_ROOT/lib/audit_log.sh"
# shellcheck source=/dev/null
source "$REPO_ROOT/lib/authorization.sh"

# Scan output never lives inside the repo — it's reconnaissance data, not
# source, and a repo directory risks it getting swept up by `git add -A`.
Expand All @@ -22,6 +24,8 @@ if ! [[ "$HOST" =~ ^[a-zA-Z0-9._-]+$ ]]; then
exit 1
fi

require_authorization "host.sh" "$HOST"

RAW_FILE="$OUTPUT_DIR/${HOST}.raw.txt"
RESULT_FILE="$OUTPUT_DIR/${HOST}.subdomains.txt"

Expand Down
4 changes: 4 additions & 0 deletions src/networking-tools/live_network_monitor.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,14 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null || echo "$SCRIPT_DIR")"
# shellcheck source=/dev/null
source "$REPO_ROOT/lib/audit_log.sh"
# shellcheck source=/dev/null
source "$REPO_ROOT/lib/authorization.sh"

# Detect the active network interface automatically
INTERFACE=$(ip route | grep default | awk '{print $5}')

require_authorization "live_network_monitor.sh" "$INTERFACE"

# Check if necessary tools are installed. This only warns — it does not
# silently sudo-install packages, since unreviewed installs on a system
# with audit/monitoring requirements need a change record, not a script.
Expand Down
4 changes: 4 additions & 0 deletions src/networking-tools/nmap/nmap.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,14 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null || echo "$SCRIPT_DIR")"
# shellcheck source=/dev/null
source "$REPO_ROOT/lib/audit_log.sh"
# shellcheck source=/dev/null
source "$REPO_ROOT/lib/authorization.sh"

SERVER="${HOST:?Set HOST to the scan target, e.g. HOST=127.0.0.1 ./nmap.sh}"
PORT_NUMBER=8080 # HTTPS port.

require_authorization "nmap.sh" "$SERVER"

set +e
nmap "$SERVER" | grep -w "$PORT_NUMBER" # Is that particular port open?
# grep -w matches whole words only,
Expand Down
Loading