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.
This commit is contained in:
@@ -0,0 +1,344 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Wazuh API Backup
|
||||
#
|
||||
# Backs up Wazuh configuration objects via the REST API.
|
||||
# Exports agents, groups, rules, decoders, CDB lists, manager
|
||||
# configuration, API users, roles, policies, and cluster status
|
||||
# to individual JSON files in a dated directory.
|
||||
#
|
||||
# Usage:
|
||||
# WAZUH_USER="wazuh-wui" WAZUH_PASS="wazuh" ./wazuh-api-backup.sh
|
||||
# WAZUH_USER="wazuh-wui" WAZUH_PASS="wazuh" ./wazuh-api-backup.sh --dry-run
|
||||
# WAZUH_USER="wazuh-wui" WAZUH_PASS="wazuh" ./wazuh-api-backup.sh --install
|
||||
#
|
||||
# Parameters:
|
||||
# --dry-run Show what would be backed up without writing files
|
||||
# --install Create cron job for daily backup at 3am
|
||||
# --help Show usage
|
||||
#
|
||||
# Environment:
|
||||
# WAZUH_API Wazuh API base URL (default: https://localhost:55000)
|
||||
# WAZUH_USER API username (default: wazuh-wui)
|
||||
# WAZUH_PASS API password (default: wazuh)
|
||||
# BACKUP_DIR Base backup directory (default: /backup/wazuh-api)
|
||||
# RETENTION_DAYS Delete backups older than this many days (default: 30)
|
||||
# CURL_TIMEOUT API request timeout in seconds (default: 15)
|
||||
#
|
||||
# Author: Phil Connor
|
||||
# Contact: contact@mylinux.work
|
||||
# Website: https://mylinux.work
|
||||
# License: MIT
|
||||
# Version: 1.01
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# --- Configuration ---
|
||||
readonly VERSION="1.0"
|
||||
readonly SCRIPT_NAME="$(basename "$0")"
|
||||
WAZUH_API="${WAZUH_API:-https://localhost:55000}"
|
||||
WAZUH_USER="${WAZUH_USER:-wazuh-wui}"
|
||||
WAZUH_PASS="${WAZUH_PASS:-wazuh}"
|
||||
BACKUP_DIR="${BACKUP_DIR:-/backup/wazuh-api}"
|
||||
RETENTION_DAYS="${RETENTION_DAYS:-30}"
|
||||
CURL_TIMEOUT="${CURL_TIMEOUT:-15}"
|
||||
DRY_RUN=false
|
||||
TOKEN=""
|
||||
|
||||
# Backup endpoints: "api_path output_filename"
|
||||
readonly ENDPOINTS=(
|
||||
"agents?limit=500 agents.json"
|
||||
"groups groups.json"
|
||||
"rules?limit=500 rules.json"
|
||||
"decoders?limit=500 decoders.json"
|
||||
"lists cdb-lists.json"
|
||||
"manager/configuration manager-config.json"
|
||||
"manager/status manager-status.json"
|
||||
"security/users users.json"
|
||||
"security/roles roles.json"
|
||||
"security/policies policies.json"
|
||||
"security/rules security-rules.json"
|
||||
"cluster/status cluster-status.json"
|
||||
"syscheck syscheck-config.json"
|
||||
"active-response active-response.json"
|
||||
)
|
||||
|
||||
# Custom rule/decoder files to export (raw XML)
|
||||
readonly CUSTOM_FILES=(
|
||||
"rules/files/local_rules.xml local_rules.xml"
|
||||
"decoders/files/local_decoder.xml local_decoder.xml"
|
||||
)
|
||||
|
||||
# --- Functions ---
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
Usage: $SCRIPT_NAME [OPTIONS]
|
||||
|
||||
Wazuh API Backup
|
||||
|
||||
Options:
|
||||
--dry-run Show what would be backed up without writing files
|
||||
--install Create cron job for daily backup at 3am
|
||||
--help Show this help message
|
||||
|
||||
Environment Variables:
|
||||
WAZUH_API Wazuh API base URL (default: https://localhost:55000)
|
||||
WAZUH_USER API username (default: wazuh-wui)
|
||||
WAZUH_PASS API password (default: wazuh)
|
||||
BACKUP_DIR Base backup directory (default: /backup/wazuh-api)
|
||||
RETENTION_DAYS Delete backups older than N days (default: 30)
|
||||
CURL_TIMEOUT Request timeout in seconds (default: 15)
|
||||
|
||||
Examples:
|
||||
WAZUH_USER="wazuh-wui" WAZUH_PASS="secret" $SCRIPT_NAME
|
||||
WAZUH_API="https://wazuh.example.com:55000" WAZUH_USER="automation" WAZUH_PASS="secret" $SCRIPT_NAME
|
||||
WAZUH_USER="wazuh-wui" WAZUH_PASS="secret" $SCRIPT_NAME --dry-run
|
||||
WAZUH_USER="wazuh-wui" WAZUH_PASS="secret" $SCRIPT_NAME --install
|
||||
EOF
|
||||
exit 0
|
||||
}
|
||||
|
||||
check_dependencies() {
|
||||
local missing=()
|
||||
for cmd in curl jq; do
|
||||
if ! command -v "$cmd" &>/dev/null; then
|
||||
missing+=("$cmd")
|
||||
fi
|
||||
done
|
||||
if [[ ${#missing[@]} -gt 0 ]]; then
|
||||
echo "ERROR: Missing required commands: ${missing[*]}" >&2
|
||||
echo "Install with: apt install ${missing[*]} OR dnf install ${missing[*]}" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
validate_config() {
|
||||
# Strip trailing slash
|
||||
WAZUH_API="${WAZUH_API%/}"
|
||||
}
|
||||
|
||||
get_token() {
|
||||
local response
|
||||
response=$(curl -sf -k --max-time "$CURL_TIMEOUT" \
|
||||
-u "${WAZUH_USER}:${WAZUH_PASS}" \
|
||||
-X POST "${WAZUH_API}/security/user/authenticate" 2>/dev/null) || {
|
||||
echo "ERROR: Failed to authenticate to Wazuh API at ${WAZUH_API}" >&2
|
||||
echo "Check WAZUH_USER, WAZUH_PASS, and API connectivity" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
TOKEN=$(echo "$response" | jq -r '.data.token // empty')
|
||||
|
||||
if [[ -z "$TOKEN" ]]; then
|
||||
echo "ERROR: Authentication succeeded but no token returned" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
api_get() {
|
||||
local endpoint="$1"
|
||||
curl -sf -k --max-time "$CURL_TIMEOUT" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
"${WAZUH_API}/${endpoint}" 2>/dev/null || echo ""
|
||||
}
|
||||
|
||||
backup_endpoint() {
|
||||
local endpoint="$1"
|
||||
local filename="$2"
|
||||
local output_dir="$3"
|
||||
local response
|
||||
|
||||
if [[ "$DRY_RUN" == true ]]; then
|
||||
printf " %-40s → %s (dry-run)\n" "$endpoint" "$filename"
|
||||
return 0
|
||||
fi
|
||||
|
||||
response=$(api_get "$endpoint")
|
||||
|
||||
if [[ -z "$response" ]]; then
|
||||
printf " %-40s → %-30s FAIL\n" "$endpoint" "$filename"
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo "$response" | jq '.' > "${output_dir}/${filename}" 2>/dev/null || {
|
||||
# Not JSON (raw XML file) — write as-is
|
||||
echo "$response" > "${output_dir}/${filename}"
|
||||
}
|
||||
local size
|
||||
size=$(du -h "${output_dir}/${filename}" | cut -f1)
|
||||
printf " %-40s → %-30s OK %s\n" "$endpoint" "$filename" "$size"
|
||||
return 0
|
||||
}
|
||||
|
||||
backup_group_configs() {
|
||||
local output_dir="$1"
|
||||
local groups_response
|
||||
|
||||
if [[ "$DRY_RUN" == true ]]; then
|
||||
printf " %-40s → %s (dry-run)\n" "groups/*/configuration" "group-*-config.json"
|
||||
return 0
|
||||
fi
|
||||
|
||||
groups_response=$(api_get "groups")
|
||||
|
||||
if [[ -z "$groups_response" ]]; then
|
||||
printf " %-40s → %-30s FAIL\n" "groups/*/configuration" "group configs"
|
||||
return 1
|
||||
fi
|
||||
|
||||
local group_names
|
||||
group_names=$(echo "$groups_response" | jq -r '.data.affected_items[].name' 2>/dev/null)
|
||||
|
||||
if [[ -z "$group_names" ]]; then
|
||||
printf " %-40s → %-30s SKIP (no groups)\n" "groups/*/configuration" "group configs"
|
||||
return 0
|
||||
fi
|
||||
|
||||
local count=0
|
||||
while IFS= read -r group; do
|
||||
local config
|
||||
config=$(api_get "groups/${group}/configuration")
|
||||
if [[ -n "$config" ]]; then
|
||||
echo "$config" | jq '.' > "${output_dir}/group-${group}-config.json" 2>/dev/null
|
||||
((count++)) || true
|
||||
fi
|
||||
done <<< "$group_names"
|
||||
|
||||
printf " %-40s → %-30s OK %d groups\n" "groups/*/configuration" "group-*-config.json" "$count"
|
||||
return 0
|
||||
}
|
||||
|
||||
cleanup_old_backups() {
|
||||
if [[ ! -d "$BACKUP_DIR" ]]; then
|
||||
return
|
||||
fi
|
||||
|
||||
local removed=0
|
||||
while IFS= read -r dir; do
|
||||
rm -rf "$dir"
|
||||
((removed++)) || true
|
||||
done < <(find "$BACKUP_DIR" -maxdepth 1 -mindepth 1 -type d -mtime +"$RETENTION_DAYS" 2>/dev/null)
|
||||
|
||||
if [[ $removed -gt 0 ]]; then
|
||||
echo "Retention: removed $removed backup(s) older than ${RETENTION_DAYS} days"
|
||||
fi
|
||||
}
|
||||
|
||||
install_cron() {
|
||||
if [[ $EUID -ne 0 ]]; then
|
||||
echo "ERROR: --install requires root" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
local script_path
|
||||
script_path=$(readlink -f "$0")
|
||||
|
||||
cat > /etc/cron.d/wazuh-api-backup <<EOF
|
||||
# Wazuh API Backup — runs daily at 3am
|
||||
WAZUH_API=${WAZUH_API}
|
||||
WAZUH_USER=${WAZUH_USER}
|
||||
WAZUH_PASS=${WAZUH_PASS}
|
||||
BACKUP_DIR=${BACKUP_DIR}
|
||||
RETENTION_DAYS=${RETENTION_DAYS}
|
||||
0 3 * * * root ${script_path} 2>/dev/null
|
||||
EOF
|
||||
|
||||
chmod 644 /etc/cron.d/wazuh-api-backup
|
||||
echo "Installed cron job: /etc/cron.d/wazuh-api-backup"
|
||||
echo "Backups will be written to: ${BACKUP_DIR}/<date>"
|
||||
}
|
||||
|
||||
# --- Main ---
|
||||
|
||||
main() {
|
||||
# Parse arguments
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
--dry-run) DRY_RUN=true ;;
|
||||
--install)
|
||||
check_dependencies
|
||||
validate_config
|
||||
install_cron
|
||||
exit 0
|
||||
;;
|
||||
--help|-h) usage ;;
|
||||
*) echo "Unknown option: $arg" >&2; usage ;;
|
||||
esac
|
||||
done
|
||||
|
||||
check_dependencies
|
||||
validate_config
|
||||
|
||||
local today
|
||||
today=$(date +%Y%m%d)
|
||||
local output_dir="${BACKUP_DIR}/${today}"
|
||||
|
||||
if [[ "$DRY_RUN" == true ]]; then
|
||||
echo "Wazuh API Backup v${VERSION} (dry-run)"
|
||||
echo "Target: ${output_dir}"
|
||||
echo ""
|
||||
else
|
||||
mkdir -p "$output_dir"
|
||||
echo "Wazuh API Backup v${VERSION}"
|
||||
echo "Target: ${output_dir}"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# Authenticate
|
||||
if [[ "$DRY_RUN" != true ]]; then
|
||||
get_token
|
||||
fi
|
||||
|
||||
local ok=0
|
||||
local fail=0
|
||||
|
||||
# Back up standard endpoints
|
||||
for entry in "${ENDPOINTS[@]}"; do
|
||||
local endpoint filename
|
||||
endpoint="${entry%% *}"
|
||||
filename="${entry##* }"
|
||||
|
||||
if backup_endpoint "$endpoint" "$filename" "$output_dir"; then
|
||||
((ok++)) || true
|
||||
else
|
||||
((fail++)) || true
|
||||
fi
|
||||
done
|
||||
|
||||
# Back up custom rule/decoder files (raw XML)
|
||||
for entry in "${CUSTOM_FILES[@]}"; do
|
||||
local endpoint filename
|
||||
endpoint="${entry%% *}"
|
||||
filename="${entry##* }"
|
||||
|
||||
if backup_endpoint "$endpoint" "$filename" "$output_dir"; then
|
||||
((ok++)) || true
|
||||
else
|
||||
((fail++)) || true
|
||||
fi
|
||||
done
|
||||
|
||||
# Back up per-group configurations
|
||||
if backup_group_configs "$output_dir"; then
|
||||
((ok++)) || true
|
||||
else
|
||||
((fail++)) || true
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
if [[ "$DRY_RUN" == true ]]; then
|
||||
local total=$((${#ENDPOINTS[@]} + ${#CUSTOM_FILES[@]} + 1))
|
||||
echo "Dry-run complete: ${total} backup targets"
|
||||
else
|
||||
local total_size
|
||||
total_size=$(du -sh "$output_dir" | cut -f1)
|
||||
echo "Complete: ${ok} OK, ${fail} failed, ${total_size} total"
|
||||
|
||||
cleanup_old_backups
|
||||
fi
|
||||
}
|
||||
|
||||
main "$@"
|
||||
Reference in New Issue
Block a user