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:
2026-05-25 03:31:08 +02:00
parent dbd6bf0324
commit a1a17e81a1
332 changed files with 174509 additions and 1106 deletions
+641
View File
@@ -0,0 +1,641 @@
#!/usr/bin/env bash
#########################################################################################
# #
# OCI Free Tier Monitor #
# Monitor Oracle Cloud Infrastructure Always Free tier usage #
# #
# Author: Phil Connor #
# Contact: contact@mylinux.work #
# License: MIT #
# Version: 1.00 #
# #
#########################################################################################
set -euo pipefail
# ── Defaults ──────────────────────────────────────────────────────────────────
WARN_PCT="${OFT_WARN_PCT:-80}"
CRIT_PCT="${OFT_CRIT_PCT:-95}"
FORMAT="text"
INTERVAL="${OFT_INTERVAL:-3600}"
SLACK_WEBHOOK="${OFT_SLACK_WEBHOOK:-}"
COMPARTMENT_ID="${OCI_COMPARTMENT_ID:-}"
OCI_PROFILE="${OCI_CLI_PROFILE:-DEFAULT}"
VERBOSE="${VERBOSE:-false}"
COLOR="${COLOR:-auto}"
RUN_MODE=""
SCRIPT_NAME="$(basename "$0")"
# ── Always Free Limits ────────────────────────────────────────────────────────
LIMIT_AMD_INSTANCES=2
LIMIT_ARM_OCPU=4
LIMIT_ARM_RAM_GB=24
LIMIT_BLOCK_STORAGE_GB=200
LIMIT_VOLUME_BACKUPS=5
LIMIT_OBJECT_STORAGE_GB=10
LIMIT_AUTONOMOUS_DB=2
LIMIT_LOAD_BALANCERS=1
# ── Colors ────────────────────────────────────────────────────────────────────
setup_colors() {
if [[ "$COLOR" == "never" ]]; then
RED="" GREEN="" YELLOW="" BLUE="" BOLD="" DIM="" RESET=""
return
fi
if [[ "$COLOR" == "auto" && ! -t 1 ]]; then
RED="" GREEN="" YELLOW="" BLUE="" BOLD="" DIM="" RESET=""
return
fi
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
BOLD='\033[1m'
DIM='\033[2m'
RESET='\033[0m'
}
# ── Logging ───────────────────────────────────────────────────────────────────
log() { printf "${GREEN}%s${RESET}\n" "$*"; }
warn() { printf "${YELLOW}⚠ %s${RESET}\n" "$*" >&2; }
err() { printf "${RED}✗ %s${RESET}\n" "$*" >&2; }
verbose() { [[ "$VERBOSE" == "true" ]] && printf "${DIM} %s${RESET}\n" "$*" >&2 || true; }
die() { err "$*"; exit 1; }
# ── Help ──────────────────────────────────────────────────────────────────────
show_help() {
cat <<EOF
Usage: $SCRIPT_NAME [MODE] [OPTIONS]
Modes:
--check Quick status check (exit 0=ok, 1=warn, 2=crit)
--report Detailed usage report for all resources
--watch Continuous monitoring loop
--alerts Show only resources exceeding thresholds
Options:
--format FMT Output format: text, json, prometheus (default: text)
--warn PCT Warning threshold percentage (default: 80)
--crit PCT Critical threshold percentage (default: 95)
--interval SECS Watch mode poll interval in seconds (default: 3600)
--slack-webhook URL Slack webhook URL for threshold alerts
--compartment-id ID OCI compartment OCID (default: tenancy root)
--no-color Disable colored output
--verbose Debug output
--help Show this help
Environment Variables:
OCI_CLI_PROFILE OCI CLI config profile (default: DEFAULT)
OCI_COMPARTMENT_ID Compartment OCID
OFT_WARN_PCT Warning threshold (default: 80)
OFT_CRIT_PCT Critical threshold (default: 95)
OFT_SLACK_WEBHOOK Slack webhook URL
OFT_INTERVAL Watch interval in seconds (default: 3600)
VERBOSE Debug output (true/false)
COLOR Color mode: auto, always, never
Examples:
$SCRIPT_NAME --check
$SCRIPT_NAME --report --format json
$SCRIPT_NAME --watch --interval 1800 --slack-webhook "https://hooks.slack.com/..."
$SCRIPT_NAME --alerts --warn 70 --crit 90
$SCRIPT_NAME --report --format prometheus > /var/lib/node_exporter/textfile/oci.prom
EOF
}
# ── Argument Parsing ──────────────────────────────────────────────────────────
parse_args() {
while [[ $# -gt 0 ]]; do
case "$1" in
--check) RUN_MODE="check"; shift ;;
--report) RUN_MODE="report"; shift ;;
--watch) RUN_MODE="watch"; shift ;;
--alerts) RUN_MODE="alerts"; shift ;;
--format) FORMAT="$2"; shift 2 ;;
--warn) WARN_PCT="$2"; shift 2 ;;
--crit) CRIT_PCT="$2"; shift 2 ;;
--interval) INTERVAL="$2"; shift 2 ;;
--slack-webhook) SLACK_WEBHOOK="$2"; shift 2 ;;
--compartment-id) COMPARTMENT_ID="$2"; shift 2 ;;
--no-color) COLOR="never"; shift ;;
--verbose) VERBOSE="true"; shift ;;
--help) show_help; exit 0 ;;
*) die "Unknown option: $1" ;;
esac
done
if [[ -z "$RUN_MODE" ]]; then err "No mode specified"; echo ""; show_help; exit 1; fi
}
# ── Dependency Check ──────────────────────────────────────────────────────────
check_deps() {
local missing=()
command -v oci >/dev/null 2>&1 || missing+=("oci")
command -v jq >/dev/null 2>&1 || missing+=("jq")
command -v curl >/dev/null 2>&1 || missing+=("curl")
if [[ ${#missing[@]} -gt 0 ]]; then
die "Missing required tools: ${missing[*]}"
fi
verbose "Dependencies satisfied: oci, jq, curl"
}
# ── OCI Helpers ───────────────────────────────────────────────────────────────
oci_cmd() {
oci --profile "$OCI_PROFILE" "$@" 2>/dev/null
}
get_compartment_id() {
if [[ -n "$COMPARTMENT_ID" ]]; then
verbose "Using compartment: $COMPARTMENT_ID"
return
fi
COMPARTMENT_ID=$(oci_cmd iam compartment list \
--include-root \
--query 'data[?contains("lifecycle-state", `ACTIVE`)] | [0]."compartment-id"' \
--raw-output 2>/dev/null || true)
if [[ -z "$COMPARTMENT_ID" ]]; then
COMPARTMENT_ID=$(oci_cmd iam region-subscription list \
--query 'data[0]."tenancy-id"' --raw-output 2>/dev/null || true)
fi
if [[ -z "$COMPARTMENT_ID" ]]; then
die "Cannot determine compartment/tenancy ID. Use --compartment-id."
fi
verbose "Resolved root compartment: $COMPARTMENT_ID"
}
get_tenancy_name() {
local name
name=$(oci_cmd iam tenancy get --tenancy-id "$COMPARTMENT_ID" \
--query 'data.name' --raw-output 2>/dev/null || echo "unknown")
echo "$name"
}
# ── Resource Check Functions ──────────────────────────────────────────────────
declare -A USAGE
declare -A LIMITS
declare -A UNITS
check_compute() {
verbose "Checking compute instances..."
local instances
instances=$(oci_cmd compute instance list \
--compartment-id "$COMPARTMENT_ID" \
--lifecycle-state RUNNING \
--query 'data' 2>/dev/null || echo "[]")
local amd_count=0
local arm_ocpu=0
local arm_ram=0
while IFS= read -r line; do
local shape
shape=$(echo "$line" | jq -r '.shape // ""')
if [[ "$shape" == *"A1"* ]] || [[ "$shape" == *"Ampere"* ]]; then
local ocpu mem
ocpu=$(echo "$line" | jq -r '."shape-config"."ocpus" // 0')
mem=$(echo "$line" | jq -r '."shape-config"."memory-in-gbs" // 0')
arm_ocpu=$(echo "$arm_ocpu + $ocpu" | bc)
arm_ram=$(echo "$arm_ram + $mem" | bc)
else
((amd_count++)) || true
fi
done < <(echo "$instances" | jq -c '.[]')
USAGE[compute_amd]=$amd_count
LIMITS[compute_amd]=$LIMIT_AMD_INSTANCES
UNITS[compute_amd]="inst"
USAGE[compute_arm_ocpu]=$arm_ocpu
LIMITS[compute_arm_ocpu]=$LIMIT_ARM_OCPU
UNITS[compute_arm_ocpu]="OCPU"
USAGE[compute_arm_ram]=$arm_ram
LIMITS[compute_arm_ram]=$LIMIT_ARM_RAM_GB
UNITS[compute_arm_ram]="GB"
verbose " AMD instances: ${amd_count}/${LIMIT_AMD_INSTANCES}"
verbose " Arm OCPU: ${arm_ocpu}/${LIMIT_ARM_OCPU}"
verbose " Arm RAM: ${arm_ram}GB/${LIMIT_ARM_RAM_GB}GB"
}
check_block_storage() {
verbose "Checking block storage..."
local volumes
volumes=$(oci_cmd bv volume list \
--compartment-id "$COMPARTMENT_ID" \
--lifecycle-state AVAILABLE \
--query 'data' 2>/dev/null || echo "[]")
local total_gb=0
while IFS= read -r size; do
total_gb=$(echo "$total_gb + $size" | bc)
done < <(echo "$volumes" | jq -r '.[]."size-in-gbs" // 0')
local backups
backups=$(oci_cmd bv volume-backup list \
--compartment-id "$COMPARTMENT_ID" \
--lifecycle-state AVAILABLE \
--query 'length(data)' 2>/dev/null || echo "0")
USAGE[block_storage]=$total_gb
LIMITS[block_storage]=$LIMIT_BLOCK_STORAGE_GB
UNITS[block_storage]="GB"
USAGE[volume_backups]=$backups
LIMITS[volume_backups]=$LIMIT_VOLUME_BACKUPS
UNITS[volume_backups]=""
verbose " Block storage: ${total_gb}GB/${LIMIT_BLOCK_STORAGE_GB}GB"
verbose " Volume backups: ${backups}/${LIMIT_VOLUME_BACKUPS}"
}
check_object_storage() {
verbose "Checking object storage..."
local namespace
namespace=$(oci_cmd os ns get --query 'data' --raw-output 2>/dev/null || echo "")
if [[ -z "$namespace" ]]; then
warn "Cannot determine object storage namespace"
USAGE[object_storage]=0
LIMITS[object_storage]=$LIMIT_OBJECT_STORAGE_GB
UNITS[object_storage]="GB"
return
fi
local buckets
buckets=$(oci_cmd os bucket list \
--compartment-id "$COMPARTMENT_ID" \
--namespace-name "$namespace" \
--query 'data[].name' 2>/dev/null || echo "[]")
local total_bytes=0
while IFS= read -r bucket; do
[[ -z "$bucket" || "$bucket" == "null" ]] && continue
local size
size=$(oci_cmd os bucket get \
--namespace-name "$namespace" \
--bucket-name "$bucket" \
--fields "approximateSize" \
--query 'data."approximate-size"' --raw-output 2>/dev/null || echo "0")
[[ "$size" == "null" ]] && size=0
total_bytes=$(echo "$total_bytes + $size" | bc)
done < <(echo "$buckets" | jq -r '.[]')
local total_gb
total_gb=$(echo "scale=1; $total_bytes / 1073741824" | bc)
USAGE[object_storage]=$total_gb
LIMITS[object_storage]=$LIMIT_OBJECT_STORAGE_GB
UNITS[object_storage]="GB"
verbose " Object storage: ${total_gb}GB/${LIMIT_OBJECT_STORAGE_GB}GB"
}
check_autonomous_db() {
verbose "Checking autonomous databases..."
local count
count=$(oci_cmd db autonomous-database list \
--compartment-id "$COMPARTMENT_ID" \
--lifecycle-state AVAILABLE \
--query 'length(data)' 2>/dev/null || echo "0")
USAGE[autonomous_db]=$count
LIMITS[autonomous_db]=$LIMIT_AUTONOMOUS_DB
UNITS[autonomous_db]=""
verbose " Autonomous DB: ${count}/${LIMIT_AUTONOMOUS_DB}"
}
check_load_balancer() {
verbose "Checking load balancers..."
local count
count=$(oci_cmd lb load-balancer list \
--compartment-id "$COMPARTMENT_ID" \
--lifecycle-state ACTIVE \
--query 'length(data)' 2>/dev/null || echo "0")
USAGE[load_balancers]=$count
LIMITS[load_balancers]=$LIMIT_LOAD_BALANCERS
UNITS[load_balancers]=""
verbose " Load balancers: ${count}/${LIMIT_LOAD_BALANCERS}"
}
# ── Calculation ───────────────────────────────────────────────────────────────
calculate_pct() {
local used="$1" limit="$2"
if [[ "$limit" == "0" ]]; then
echo "0"
return
fi
echo "scale=0; ($used * 100) / $limit" | bc
}
get_status() {
local pct="$1"
if (( pct >= CRIT_PCT )); then
echo "critical"
elif (( pct >= WARN_PCT )); then
echo "warning"
else
echo "ok"
fi
}
# ── Collect All Data ──────────────────────────────────────────────────────────
RESOURCE_ORDER=(compute_amd compute_arm_ocpu compute_arm_ram block_storage volume_backups object_storage autonomous_db load_balancers)
RESOURCE_LABELS=(
"Compute (AMD)"
"Compute (Arm OCPU)"
"Compute (Arm RAM)"
"Block Storage"
"Volume Backups"
"Object Storage"
"Autonomous DB"
"Load Balancers"
)
collect_all() {
check_compute
check_block_storage
check_object_storage
check_autonomous_db
check_load_balancer
}
# ── Output Formatters ─────────────────────────────────────────────────────────
format_text() {
local alerts_only="${1:-false}"
local tenancy
tenancy=$(get_tenancy_name)
printf "\n${BOLD}OCI Free Tier Monitor${RESET}\n"
printf "Tenancy: %s\n" "$tenancy"
printf "Time: %s\n" "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
printf "\n ── Resource Usage ──\n\n"
printf " %-22s %-12s %-12s %-8s %s\n" "Resource" "Used" "Limit" "Usage" "Status"
printf " %s\n" "$(printf '%.0s─' {1..64})"
local ok_count=0 warn_count=0 crit_count=0
for i in "${!RESOURCE_ORDER[@]}"; do
local key="${RESOURCE_ORDER[$i]}"
local label="${RESOURCE_LABELS[$i]}"
local used="${USAGE[$key]}"
local limit="${LIMITS[$key]}"
local unit="${UNITS[$key]}"
local pct
pct=$(calculate_pct "$used" "$limit")
local status
status=$(get_status "$pct")
case "$status" in
ok) ((ok_count++)) || true; status_str="${GREEN}✓ OK${RESET}" ;;
warning) ((warn_count++)) || true; status_str="${YELLOW}⚠ Warning${RESET}" ;;
critical) ((crit_count++)) || true; status_str="${RED}✗ Critical${RESET}" ;;
esac
if [[ "$alerts_only" == "true" && "$status" == "ok" ]]; then
continue
fi
local used_str="${used}${unit:+ $unit}"
local limit_str="${limit}${unit:+ $unit}"
printf " %-22s %-12s %-12s %3s%% ${status_str}\n" \
"$label" "$used_str" "$limit_str" "$pct"
done
printf "\n Summary: %s OK, %s Warning, %s Critical\n\n" \
"$ok_count" "$warn_count" "$crit_count"
}
format_json() {
local alerts_only="${1:-false}"
local resources="[]"
for i in "${!RESOURCE_ORDER[@]}"; do
local key="${RESOURCE_ORDER[$i]}"
local label="${RESOURCE_LABELS[$i]}"
local used="${USAGE[$key]}"
local limit="${LIMITS[$key]}"
local pct
pct=$(calculate_pct "$used" "$limit")
local status
status=$(get_status "$pct")
if [[ "$alerts_only" == "true" && "$status" == "ok" ]]; then
continue
fi
resources=$(echo "$resources" | jq \
--arg key "$key" \
--arg label "$label" \
--argjson used "$used" \
--argjson limit "$limit" \
--argjson pct "$pct" \
--arg status "$status" \
'. + [{"resource": $key, "label": $label, "used": $used, "limit": $limit, "percent": $pct, "status": $status}]')
done
jq -n \
--arg time "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
--argjson warn "$WARN_PCT" \
--argjson crit "$CRIT_PCT" \
--argjson resources "$resources" \
'{"timestamp": $time, "warn_threshold": $warn, "crit_threshold": $crit, "resources": $resources}'
}
format_prometheus() {
echo "# HELP oci_free_tier_usage_percent OCI Free Tier resource usage percentage"
echo "# TYPE oci_free_tier_usage_percent gauge"
for i in "${!RESOURCE_ORDER[@]}"; do
local key="${RESOURCE_ORDER[$i]}"
local used="${USAGE[$key]}"
local limit="${LIMITS[$key]}"
local pct
pct=$(calculate_pct "$used" "$limit")
echo "oci_free_tier_usage_percent{resource=\"${key}\"} ${pct}"
done
echo "# HELP oci_free_tier_used OCI Free Tier resource current usage"
echo "# TYPE oci_free_tier_used gauge"
for i in "${!RESOURCE_ORDER[@]}"; do
local key="${RESOURCE_ORDER[$i]}"
echo "oci_free_tier_used{resource=\"${key}\"} ${USAGE[$key]}"
done
echo "# HELP oci_free_tier_limit OCI Free Tier resource limit"
echo "# TYPE oci_free_tier_limit gauge"
for i in "${!RESOURCE_ORDER[@]}"; do
local key="${RESOURCE_ORDER[$i]}"
echo "oci_free_tier_limit{resource=\"${key}\"} ${LIMITS[$key]}"
done
echo "# HELP oci_free_tier_warn_threshold Warning threshold percentage"
echo "# TYPE oci_free_tier_warn_threshold gauge"
echo "oci_free_tier_warn_threshold ${WARN_PCT}"
echo "# HELP oci_free_tier_crit_threshold Critical threshold percentage"
echo "# TYPE oci_free_tier_crit_threshold gauge"
echo "oci_free_tier_crit_threshold ${CRIT_PCT}"
}
format_output() {
local alerts_only="${1:-false}"
case "$FORMAT" in
text) format_text "$alerts_only" ;;
json) format_json "$alerts_only" ;;
prometheus) format_prometheus ;;
*) die "Unknown format: $FORMAT" ;;
esac
}
# ── Slack Notification ────────────────────────────────────────────────────────
send_slack_alert() {
[[ -z "$SLACK_WEBHOOK" ]] && return
local breached=()
for i in "${!RESOURCE_ORDER[@]}"; do
local key="${RESOURCE_ORDER[$i]}"
local label="${RESOURCE_LABELS[$i]}"
local used="${USAGE[$key]}"
local limit="${LIMITS[$key]}"
local pct
pct=$(calculate_pct "$used" "$limit")
local status
status=$(get_status "$pct")
if [[ "$status" != "ok" ]]; then
breached+=("${label}: ${used}/${limit} (${pct}%) [${status}]")
fi
done
if [[ ${#breached[@]} -eq 0 ]]; then
verbose "No threshold breaches — skipping Slack notification"
return
fi
local message="OCI Free Tier Alert — $(date -u +%Y-%m-%dT%H:%M:%SZ)\n"
for line in "${breached[@]}"; do
message+="${line}\n"
done
local payload
payload=$(jq -n --arg text "$message" '{"text": $text}')
if curl -sf -o /dev/null -X POST \
-H "Content-Type: application/json" \
-d "$payload" "$SLACK_WEBHOOK"; then
verbose "Slack notification sent"
else
warn "Failed to send Slack notification"
fi
}
# ── Exit Code ─────────────────────────────────────────────────────────────────
get_exit_code() {
local max_status="ok"
for key in "${RESOURCE_ORDER[@]}"; do
local used="${USAGE[$key]}"
local limit="${LIMITS[$key]}"
local pct
pct=$(calculate_pct "$used" "$limit")
local status
status=$(get_status "$pct")
if [[ "$status" == "critical" ]]; then
max_status="critical"
break
elif [[ "$status" == "warning" ]]; then
max_status="warning"
fi
done
case "$max_status" in
ok) echo 0 ;;
warning) echo 1 ;;
critical) echo 2 ;;
esac
}
# ── Mode Functions ────────────────────────────────────────────────────────────
run_check() {
collect_all
format_output "false"
send_slack_alert
local code
code=$(get_exit_code)
exit "$code"
}
run_report() {
collect_all
format_output "false"
send_slack_alert
}
run_alerts() {
collect_all
format_output "true"
send_slack_alert
local code
code=$(get_exit_code)
exit "$code"
}
run_watch() {
log "Starting watch mode (interval: ${INTERVAL}s)"
while true; do
collect_all
format_output "false"
send_slack_alert
verbose "Next check in ${INTERVAL}s"
sleep "$INTERVAL"
done
}
# ── Main ──────────────────────────────────────────────────────────────────────
main() {
parse_args "$@"
setup_colors
check_deps
get_compartment_id
case "$RUN_MODE" in
check) run_check ;;
report) run_report ;;
alerts) run_alerts ;;
watch) run_watch ;;
esac
}
main "$@"