108 lines
4.2 KiB
Bash
108 lines
4.2 KiB
Bash
#!/usr/bin/env bash
|
|
# UniFi UDM Pro — Integration API helper.
|
|
#
|
|
# Uso:
|
|
# query.sh <path> [curl args...]
|
|
#
|
|
# El <path> puede ser:
|
|
# - Path corto: /sites → se prefija /proxy/network/integration/v1
|
|
# - Path /proxy: /proxy/network/... → se usa tal cual (sirve para Classic API)
|
|
# - URL completa: https://... → se usa tal cual
|
|
|
|
set -euo pipefail
|
|
|
|
SKILL_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
ENV_FILE="$SKILL_DIR/.env"
|
|
|
|
if [[ ! -f "$ENV_FILE" ]]; then
|
|
echo "ERROR: $ENV_FILE no existe." >&2
|
|
echo " cp $SKILL_DIR/.env.example $ENV_FILE y completá UNIFI_API_KEY." >&2
|
|
exit 1
|
|
fi
|
|
|
|
set -a
|
|
# shellcheck disable=SC1090
|
|
source "$ENV_FILE"
|
|
set +a
|
|
|
|
: "${UNIFI_HOST:?UNIFI_HOST no definido en .env}"
|
|
: "${UNIFI_API_KEY:?UNIFI_API_KEY no definido en .env}"
|
|
: "${UNIFI_SITE:?UNIFI_SITE no definido en .env (debe ser el UUID del site, no el nombre)}"
|
|
|
|
PATH_ARG="${1:-}"
|
|
shift || true
|
|
|
|
if [[ -z "$PATH_ARG" ]]; then
|
|
cat >&2 <<EOF
|
|
Uso: query.sh <path> [curl args...]
|
|
|
|
Ejemplos:
|
|
query.sh /sites
|
|
query.sh /sites/{site}/devices
|
|
query.sh /sites/{site}/clients
|
|
query.sh /sites/{site}/devices/<deviceId>/statistics/latest
|
|
|
|
El placeholder {site} se reemplaza por \$UNIFI_SITE (UUID del site, en .env).
|
|
Para Classic API usar query-classic.sh (login flow distinto).
|
|
EOF
|
|
exit 2
|
|
fi
|
|
|
|
# ──────────────────────────────────────────────────────────────────────────
|
|
# READ-ONLY GUARD — la skill es read-only por diseño. Bloqueamos cualquier
|
|
# intento de cambiar el verbo HTTP o mandar body. La protección REAL la da
|
|
# el rol "Site View Only" del admin en el UDM (que también devuelve 403);
|
|
# este guard es defensa en profundidad para fallar rápido sin salir a la red.
|
|
# ──────────────────────────────────────────────────────────────────────────
|
|
for arg in "$@"; do
|
|
case "$arg" in
|
|
-X|--request|-XPOST|-XPUT|-XDELETE|-XPATCH)
|
|
echo "ERROR: la skill 'unifi' es read-only. -X/--request bloqueado." >&2
|
|
exit 3
|
|
;;
|
|
-d|--data|--data-raw|--data-binary|--data-urlencode|-T|--upload-file)
|
|
echo "ERROR: la skill 'unifi' es read-only. -d/--data/-T bloqueado." >&2
|
|
exit 3
|
|
;;
|
|
esac
|
|
done
|
|
|
|
# ──────────────────────────────────────────────────────────────────────────
|
|
# READ-ONLY GUARD — la skill es read-only por diseño. Bloqueamos cualquier
|
|
# intento de cambiar el verbo HTTP o mandar body. La protección REAL la da
|
|
# el rol "Site View Only" del admin en el UDM (que también devuelve 403);
|
|
# este guard es defensa en profundidad para evitar errores aun antes de
|
|
# salir a la red.
|
|
# ──────────────────────────────────────────────────────────────────────────
|
|
for arg in "$@"; do
|
|
case "$arg" in
|
|
-X|--request|-XPOST|-XPUT|-XDELETE|-XPATCH)
|
|
echo "ERROR: la skill 'unifi' es read-only. -X/--request bloqueado." >&2
|
|
echo " Si REALMENTE necesitás escribir, llamá a curl directo (no via este script)" >&2
|
|
echo " y sabé lo que estás haciendo." >&2
|
|
exit 3
|
|
;;
|
|
-d|--data|--data-raw|--data-binary|--data-urlencode|-T|--upload-file)
|
|
echo "ERROR: la skill 'unifi' es read-only. -d/--data/-T bloqueado." >&2
|
|
exit 3
|
|
;;
|
|
esac
|
|
done
|
|
|
|
# Expandir el placeholder {site} con el UUID del site (Integration API usa UUID, no nombre).
|
|
PATH_ARG="${PATH_ARG//\{site\}/$UNIFI_SITE}"
|
|
|
|
if [[ "$PATH_ARG" =~ ^https?:// ]]; then
|
|
URL="$PATH_ARG"
|
|
elif [[ "$PATH_ARG" == /proxy/* || "$PATH_ARG" == /api/* ]]; then
|
|
URL="https://${UNIFI_HOST}${PATH_ARG}"
|
|
else
|
|
URL="https://${UNIFI_HOST}/proxy/network/integration/v1${PATH_ARG}"
|
|
fi
|
|
|
|
exec curl -sS -k \
|
|
-H "X-API-KEY: ${UNIFI_API_KEY}" \
|
|
-H "Accept: application/json" \
|
|
"$@" \
|
|
"$URL"
|