#!/usr/bin/env bash # UniFi UDM Pro — Integration API helper. # # Uso: # query.sh [curl args...] # # El 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 < [curl args...] Ejemplos: query.sh /sites query.sh /sites/{site}/devices query.sh /sites/{site}/clients query.sh /sites/{site}/devices//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"