Files
linux-scripts/wickr-metrics-exporter.sh
chiefgeek a1a17e81a1 Sync all scripts from website downloads — 352 scripts total
Includes updated JS challenge scripts with Claude-User whitelist,
same-site referer bypass, Blackbox-Exporter allowed bot, and all
new exporters, cheat sheets, and automation scripts.
2026-05-25 03:31:08 +02:00

400 lines
12 KiB
Bash

#!/bin/bash
################################################
#### Wickr Enterprise Metrics Collector ####
#### for Prometheus node_exporter textfile ####
#### ####
#### Author: Phil Connor ####
#### Contact: contact@mylinux.work ####
#### Version: 1.00-030726 ####
################################################
set -o pipefail
SCRIPT_NAME=$(basename "$0")
readonly SCRIPT_NAME
# Default configuration
readonly DEFAULT_NODE_DIR="/var/lib/node_exporter"
readonly DEFAULT_COLLECTION_INTERVAL=300
readonly DEFAULT_CURL_TIMEOUT=30
# Configuration variables (can be overridden by environment)
WICKR_ADMIN_URL=${WICKR_ADMIN_URL:-}
WICKR_API_TOKEN=${WICKR_API_TOKEN:-}
NODE_DIR=${NODE_DIR:-$DEFAULT_NODE_DIR}
COLLECTION_INTERVAL=${COLLECTION_INTERVAL:-$DEFAULT_COLLECTION_INTERVAL}
DEBUG=${DEBUG:-}
# Runtime flags
RUN_MODE="once"
# Error tracking
ERRORS_TOTAL=0
handle_error() {
local exit_code=$1
local line_number=$2
echo "Error: $SCRIPT_NAME failed at line $line_number with exit code $exit_code" >&2
exit "$exit_code"
}
trap 'handle_error $? $LINENO' ERR
debug_echo() {
if [[ -n "$DEBUG" ]]; then
echo "[DEBUG] $*" >&2
fi
}
show_help() {
cat << EOF
Usage: $SCRIPT_NAME [OPTIONS]
Wickr Enterprise metrics collector for Prometheus node_exporter textfile directory.
Collects user, bot, device, security group, and network statistics from the
Wickr Enterprise Admin API and writes them as Prometheus metrics.
OPTIONS:
--once Run collection once and exit (default)
--daemon Run continuously at COLLECTION_INTERVAL
--help, -h Show this help message
ENVIRONMENT VARIABLES:
WICKR_ADMIN_URL Wickr Enterprise admin URL (required, e.g. https://wickr.example.com)
WICKR_API_TOKEN Admin API token (required — generate in Admin Console → API Access)
NODE_DIR Node exporter textfile directory (default: $DEFAULT_NODE_DIR)
COLLECTION_INTERVAL Seconds between collections in daemon mode (default: $DEFAULT_COLLECTION_INTERVAL)
DEBUG Enable debug output
EXAMPLES:
WICKR_ADMIN_URL=https://wickr.example.com WICKR_API_TOKEN=abc123 $SCRIPT_NAME --once
WICKR_ADMIN_URL=https://wickr.example.com WICKR_API_TOKEN=abc123 $SCRIPT_NAME --daemon
OUTPUT:
Writes metrics to \$NODE_DIR/textfile_collector/wickr_metrics.prom
EOF
exit 0
}
# Parse arguments
while [[ $# -gt 0 ]]; do
case "$1" in
--once) RUN_MODE="once"; shift ;;
--daemon) RUN_MODE="daemon"; shift ;;
--help|-h) show_help ;;
*) echo "Unknown option: $1" >&2; show_help ;;
esac
done
# Validate required variables
validate_config() {
if [[ -z "$WICKR_ADMIN_URL" ]]; then
echo "Error: WICKR_ADMIN_URL is required" >&2
exit 1
fi
if [[ -z "$WICKR_API_TOKEN" ]]; then
echo "Error: WICKR_API_TOKEN is required" >&2
exit 1
fi
# Strip trailing slash
WICKR_ADMIN_URL="${WICKR_ADMIN_URL%/}"
# Check textfile collector directory
local textfile_dir="${NODE_DIR}/textfile_collector"
if [[ ! -d "$textfile_dir" ]]; then
echo "Error: Textfile collector directory not found: $textfile_dir" >&2
echo "Create it: sudo mkdir -p $textfile_dir" >&2
exit 1
fi
}
# API helper — makes authenticated requests to the Wickr Admin API
wickr_api() {
local endpoint="$1"
local url="${WICKR_ADMIN_URL}/api/v1${endpoint}"
debug_echo "GET $url"
local response
response=$(curl -sf --max-time "$DEFAULT_CURL_TIMEOUT" \
-H "Authorization: Bearer ${WICKR_API_TOKEN}" \
-H "Accept: application/json" \
"$url" 2>/dev/null)
local exit_code=$?
if [[ $exit_code -ne 0 ]]; then
debug_echo "API call failed: $url (exit code $exit_code)"
ERRORS_TOTAL=$((ERRORS_TOTAL + 1))
return 1
fi
echo "$response"
}
# Count items from a paginated API response
# Uses jq to count array items, handles pagination via response headers
wickr_api_count() {
local endpoint="$1"
local url="${WICKR_ADMIN_URL}/api/v1${endpoint}"
debug_echo "HEAD $url (count)"
# Try to get total from response headers or count array items
local response
response=$(curl -sf --max-time "$DEFAULT_CURL_TIMEOUT" \
-H "Authorization: Bearer ${WICKR_API_TOKEN}" \
-H "Accept: application/json" \
"$url" 2>/dev/null)
if [[ $? -ne 0 ]]; then
debug_echo "API count failed: $url"
ERRORS_TOTAL=$((ERRORS_TOTAL + 1))
echo "0"
return 1
fi
# Try to count array items
if command -v jq &>/dev/null; then
local count
count=$(echo "$response" | jq 'if type == "array" then length elif .data? and (.data | type == "array") then .data | length elif .total? then .total elif .count? then .count else 0 end' 2>/dev/null)
echo "${count:-0}"
else
echo "0"
fi
}
# Collect user metrics
collect_users() {
debug_echo "Collecting user metrics..."
local users_response
users_response=$(wickr_api "/users") || return 1
if command -v jq &>/dev/null && [[ -n "$users_response" ]]; then
local total active suspended pending
total=$(echo "$users_response" | jq 'if type == "array" then length elif .data? then (.data | length) elif .total? then .total else 0 end' 2>/dev/null)
active=$(echo "$users_response" | jq '[if type == "array" then .[] elif .data? then .data[] else empty end | select(.status? == "active" or .status? == "Active")] | length' 2>/dev/null)
suspended=$(echo "$users_response" | jq '[if type == "array" then .[] elif .data? then .data[] else empty end | select(.status? == "suspended" or .status? == "Suspended")] | length' 2>/dev/null)
pending=$(echo "$users_response" | jq '[if type == "array" then .[] elif .data? then .data[] else empty end | select(.status? == "pending" or .status? == "Pending")] | length' 2>/dev/null)
cat <<EOF
# HELP wickr_users_total Total number of Wickr users.
# TYPE wickr_users_total gauge
wickr_users_total ${total:-0}
# HELP wickr_users_active Number of active Wickr users.
# TYPE wickr_users_active gauge
wickr_users_active ${active:-0}
# HELP wickr_users_suspended Number of suspended Wickr users.
# TYPE wickr_users_suspended gauge
wickr_users_suspended ${suspended:-0}
# HELP wickr_users_pending Number of pending Wickr users.
# TYPE wickr_users_pending gauge
wickr_users_pending ${pending:-0}
EOF
fi
}
# Collect bot metrics
collect_bots() {
debug_echo "Collecting bot metrics..."
local bots_response
bots_response=$(wickr_api "/bots") || return 1
if command -v jq &>/dev/null && [[ -n "$bots_response" ]]; then
local total active
total=$(echo "$bots_response" | jq 'if type == "array" then length elif .data? then (.data | length) elif .total? then .total else 0 end' 2>/dev/null)
active=$(echo "$bots_response" | jq '[if type == "array" then .[] elif .data? then .data[] else empty end | select(.status? == "active" or .status? == "Active" or .status? == "online" or .status? == "Online")] | length' 2>/dev/null)
cat <<EOF
# HELP wickr_bots_total Total number of Wickr bots.
# TYPE wickr_bots_total gauge
wickr_bots_total ${total:-0}
# HELP wickr_bots_active Number of active Wickr bots.
# TYPE wickr_bots_active gauge
wickr_bots_active ${active:-0}
EOF
fi
}
# Collect security group metrics
collect_security_groups() {
debug_echo "Collecting security group metrics..."
local sg_response
sg_response=$(wickr_api "/securitygroups") || return 1
if command -v jq &>/dev/null && [[ -n "$sg_response" ]]; then
local total
total=$(echo "$sg_response" | jq 'if type == "array" then length elif .data? then (.data | length) elif .total? then .total else 0 end' 2>/dev/null)
cat <<EOF
# HELP wickr_security_groups_total Total number of security groups.
# TYPE wickr_security_groups_total gauge
wickr_security_groups_total ${total:-0}
EOF
# Per-group user counts if available
echo "$sg_response" | jq -r '
(if type == "array" then . elif .data? then .data else [] end)[]
| select(.name? != null)
| "wickr_security_group_users{group=\"\(.name)\"} \(.userCount // .user_count // 0)"
' 2>/dev/null | while IFS= read -r line; do
if [[ -z "$_sg_header_printed" ]]; then
echo "# HELP wickr_security_group_users Number of users per security group."
echo "# TYPE wickr_security_group_users gauge"
_sg_header_printed=1
fi
echo "$line"
done
echo ""
fi
}
# Collect network metrics
collect_networks() {
debug_echo "Collecting network metrics..."
local net_response
net_response=$(wickr_api "/networks") || return 1
if command -v jq &>/dev/null && [[ -n "$net_response" ]]; then
local total
total=$(echo "$net_response" | jq 'if type == "array" then length elif .data? then (.data | length) elif .total? then .total else 0 end' 2>/dev/null)
cat <<EOF
# HELP wickr_networks_total Total number of Wickr networks.
# TYPE wickr_networks_total gauge
wickr_networks_total ${total:-0}
EOF
fi
}
# Collect device metrics (aggregate from users)
collect_devices() {
debug_echo "Collecting device metrics..."
local users_response
users_response=$(wickr_api "/users") || return 1
if command -v jq &>/dev/null && [[ -n "$users_response" ]]; then
local device_count
device_count=$(echo "$users_response" | jq '
[if type == "array" then .[] elif .data? then .data[] else empty end
| (.devices // .device_count // 0)
| if type == "array" then length else . end] | add // 0
' 2>/dev/null)
cat <<EOF
# HELP wickr_devices_total Total number of registered devices.
# TYPE wickr_devices_total gauge
wickr_devices_total ${device_count:-0}
EOF
fi
}
# Check API reachability
collect_health() {
debug_echo "Checking Wickr API health..."
local start_time end_time duration_ms
start_time=$(date +%s%N)
if curl -sf --max-time "$DEFAULT_CURL_TIMEOUT" \
-H "Authorization: Bearer ${WICKR_API_TOKEN}" \
"${WICKR_ADMIN_URL}/api/v1/networks" &>/dev/null; then
local up=1
else
local up=0
fi
end_time=$(date +%s%N)
duration_ms=$(( (end_time - start_time) / 1000000 ))
cat <<EOF
# HELP wickr_api_up Whether the Wickr Admin API is reachable (1=up, 0=down).
# TYPE wickr_api_up gauge
wickr_api_up $up
# HELP wickr_api_response_time_ms Wickr Admin API response time in milliseconds.
# TYPE wickr_api_response_time_ms gauge
wickr_api_response_time_ms $duration_ms
EOF
}
# Write collection metadata
collect_metadata() {
cat <<EOF
# HELP wickr_exporter_errors_total Total number of errors during collection.
# TYPE wickr_exporter_errors_total counter
wickr_exporter_errors_total $ERRORS_TOTAL
# HELP wickr_exporter_last_success_timestamp Unix timestamp of last successful collection.
# TYPE wickr_exporter_last_success_timestamp gauge
wickr_exporter_last_success_timestamp $(date +%s)
EOF
}
# Main collection function
collect_all() {
ERRORS_TOTAL=0
local output_dir="${NODE_DIR}/textfile_collector"
local output_file="${output_dir}/wickr_metrics.prom"
local temp_file
temp_file=$(mktemp "${output_file}.XXXXXX")
debug_echo "Starting collection..."
{
collect_health
collect_users
collect_bots
collect_security_groups
collect_networks
collect_devices
collect_metadata
} > "$temp_file" 2>/dev/null
mv "$temp_file" "$output_file"
debug_echo "Collection complete. Wrote to $output_file (errors: $ERRORS_TOTAL)"
}
# Main
main() {
validate_config
case "$RUN_MODE" in
once)
collect_all
;;
daemon)
echo "$SCRIPT_NAME running in daemon mode (interval: ${COLLECTION_INTERVAL}s)"
while true; do
collect_all
sleep "$COLLECTION_INTERVAL"
done
;;
esac
}
main