147 lines
4.1 KiB
Bash
147 lines
4.1 KiB
Bash
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
helper_dir=${SLOPTRAP_HELPER_DIR:-/run/sloptrap-helper}
|
|
queue_dir="$helper_dir/queue"
|
|
caps=${SLOPTRAP_ACTIVE_CAPABILITIES:-}
|
|
audit_log=${SLOPTRAP_AUDIT_LOG:-/codex/state/capabilities.log}
|
|
mkdir -p "$queue_dir" "$(dirname "$audit_log")"
|
|
|
|
has_capability() {
|
|
local needle=$1
|
|
local token
|
|
for token in $caps; do
|
|
if [[ $token == "$needle" ]]; then
|
|
return 0
|
|
fi
|
|
done
|
|
return 1
|
|
}
|
|
|
|
log_action() {
|
|
local op=$1
|
|
local details=$2
|
|
local status=$3
|
|
printf '%s op=%s status=%s %s\n' "$(date -u +%FT%TZ)" "$op" "$status" "$details" >>"$audit_log"
|
|
}
|
|
|
|
write_status() {
|
|
local request_dir=$1
|
|
local status=$2
|
|
printf '%s\n' "$status" >"$request_dir/status"
|
|
}
|
|
|
|
run_apt_install() {
|
|
local request_dir=$1
|
|
has_capability "apt-install" || {
|
|
printf 'capability apt-install is not active\n' >"$request_dir/stderr"
|
|
write_status "$request_dir" 126
|
|
log_action "apt-install" "packages=denied" 126
|
|
return
|
|
}
|
|
local packages_file="$request_dir/packages"
|
|
if [[ ! -f $packages_file ]]; then
|
|
printf 'missing package list\n' >"$request_dir/stderr"
|
|
write_status "$request_dir" 2
|
|
log_action "apt-install" "packages=missing" 2
|
|
return
|
|
fi
|
|
mapfile -t packages <"$packages_file"
|
|
if [[ ${#packages[@]} -eq 0 ]]; then
|
|
printf 'package list is empty\n' >"$request_dir/stderr"
|
|
write_status "$request_dir" 2
|
|
log_action "apt-install" "packages=empty" 2
|
|
return
|
|
fi
|
|
if apt-get update >"$request_dir/stdout" 2>"$request_dir/stderr" \
|
|
&& apt-get install -y --no-install-recommends "${packages[@]}" >>"$request_dir/stdout" 2>>"$request_dir/stderr"; then
|
|
write_status "$request_dir" 0
|
|
log_action "apt-install" "packages=${packages[*]}" 0
|
|
return
|
|
fi
|
|
write_status "$request_dir" 1
|
|
log_action "apt-install" "packages=${packages[*]}" 1
|
|
}
|
|
|
|
run_packet_capture() {
|
|
local request_dir=$1
|
|
has_capability "packet-capture" || {
|
|
printf 'capability packet-capture is not active\n' >"$request_dir/stderr"
|
|
write_status "$request_dir" 126
|
|
log_action "packet-capture" "interface=denied" 126
|
|
return
|
|
}
|
|
local iface_file="$request_dir/interface"
|
|
[[ -f $iface_file ]] || {
|
|
printf 'missing interface\n' >"$request_dir/stderr"
|
|
write_status "$request_dir" 2
|
|
log_action "packet-capture" "interface=missing" 2
|
|
return
|
|
}
|
|
local iface filter_file output_file stdout_mode
|
|
iface=$(<"$iface_file")
|
|
filter_file="$request_dir/filter"
|
|
output_file="$request_dir/output"
|
|
stdout_mode=0
|
|
[[ -f "$request_dir/stdout_mode" ]] && stdout_mode=$(<"$request_dir/stdout_mode")
|
|
local -a cmd=(tcpdump -i "$iface")
|
|
if [[ -s $filter_file ]]; then
|
|
local filter
|
|
filter=$(<"$filter_file")
|
|
local -a filter_tokens=()
|
|
read -r -a filter_tokens <<< "$filter"
|
|
cmd+=("${filter_tokens[@]}")
|
|
fi
|
|
if [[ -s $output_file ]]; then
|
|
local capture_path
|
|
capture_path=$(<"$output_file")
|
|
mkdir -p "$(dirname "$capture_path")"
|
|
cmd+=(-w "$capture_path")
|
|
fi
|
|
if [[ $stdout_mode == "1" ]]; then
|
|
"${cmd[@]}" >"$request_dir/stdout" 2>"$request_dir/stderr" || {
|
|
write_status "$request_dir" 1
|
|
log_action "packet-capture" "interface=$iface stdout=1" 1
|
|
return
|
|
}
|
|
else
|
|
"${cmd[@]}" >"$request_dir/stdout" 2>"$request_dir/stderr" || {
|
|
write_status "$request_dir" 1
|
|
log_action "packet-capture" "interface=$iface stdout=0" 1
|
|
return
|
|
}
|
|
fi
|
|
write_status "$request_dir" 0
|
|
log_action "packet-capture" "interface=$iface stdout=$stdout_mode" 0
|
|
}
|
|
|
|
while true; do
|
|
shopt -s nullglob
|
|
request_dirs=("$queue_dir"/*.req)
|
|
shopt -u nullglob
|
|
if [[ ${#request_dirs[@]} -eq 0 ]]; then
|
|
sleep 1
|
|
continue
|
|
fi
|
|
for request_dir in "${request_dirs[@]}"; do
|
|
[[ -d $request_dir ]] || continue
|
|
[[ ! -f "$request_dir/status" ]] || continue
|
|
op=$(<"$request_dir/op")
|
|
: >"$request_dir/stdout"
|
|
: >"$request_dir/stderr"
|
|
case "$op" in
|
|
apt-install)
|
|
run_apt_install "$request_dir"
|
|
;;
|
|
packet-capture)
|
|
run_packet_capture "$request_dir"
|
|
;;
|
|
*)
|
|
printf 'unknown operation %s\n' "$op" >"$request_dir/stderr"
|
|
write_status "$request_dir" 2
|
|
log_action "$op" "unknown=1" 2
|
|
;;
|
|
esac
|
|
done
|
|
done
|