Files
skill-bitwarden/scripts/query.sh

140 lines
4.6 KiB
Bash

#!/usr/bin/env bash
# bitwarden skill — helper REST autenticado.
#
# Uso:
# query.sh /status # GET
# query.sh /list/object/items # GET
# query.sh "/object/item/<uuid>" # GET
# query.sh /generate?length=20&special=true # GET
# query.sh -X POST -H 'Content-Type: application/json' \
# -d '{"name":"foo"}' /object/folder # POST (create)
#
# Garantiza que `bw serve` esté arriba antes de llamar.
#
# READ + CREATE ONLY:
# - GET siempre permitido
# - POST permitido sólo en /object/item, /object/folder, /object/send,
# /sync, /unlock, /lock, /generate (sí, hay POST /generate también),
# y endpoints de auth
# - PUT/DELETE/PATCH bloqueados
# - POST a endpoints de mutación (move/restore/confirm/attachment/share)
# bloqueados
#
# El guard NO es la única defensa: el server de Vaultwarden también rechaza
# escritura en collections del org NucleOS porque claudecode0 está como
# "Can view". Para el vault personal de claudecode0, este guard ES la única
# defensa contra modify/delete.
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. cp $SKILL_DIR/.env.example $ENV_FILE" >&2
exit 1
fi
set -a
# shellcheck disable=SC1090
source "$ENV_FILE"
set +a
PORT="${BW_PORT:-8087}"
BASE="http://127.0.0.1:${PORT}"
# ─── Parsear args: separar flags de curl del path ───────────────────────
args=()
path=""
method="GET"
while [[ $# -gt 0 ]]; do
case "$1" in
-X|--request)
method="$(echo "${2:-GET}" | tr '[:lower:]' '[:upper:]')"
args+=("$1" "$2"); shift 2
;;
-X*)
method="$(echo "${1#-X}" | tr '[:lower:]' '[:upper:]')"
args+=("$1"); shift
;;
--request=*)
method="$(echo "${1#--request=}" | tr '[:lower:]' '[:upper:]')"
args+=("$1"); shift
;;
-d|--data|--data-raw|--data-binary|--data-urlencode|-H|--header|-o|--output|-T|--upload-file)
args+=("$1" "$2"); shift 2
;;
--) shift; break ;;
-*) args+=("$1"); shift ;;
*) path="$1"; shift ;;
esac
done
# Cualquier residual posicional
[[ $# -gt 0 && -z "$path" ]] && path="$1"
if [[ -z "$path" ]]; then
cat >&2 <<EOF
Uso: query.sh [curl flags] <path>
Read examples:
query.sh /status
query.sh /list/object/items
query.sh /list/object/folders
query.sh "/object/item/<uuid>"
query.sh "/object/password/<uuid>"
query.sh "/generate?length=20&special=true"
Create examples (POST):
query.sh -X POST -H 'Content-Type: application/json' \\
-d '{"name":"new folder"}' /object/folder
Ver endpoints.md para la cheat sheet completa.
EOF
exit 2
fi
# Asegurar leading /
case "$path" in
/*) ;;
http*) echo "ERROR: pasá solo el path, no URL completa." >&2; exit 1 ;;
*) path="/$path" ;;
esac
# ─── READ + CREATE GUARD ────────────────────────────────────────────────
case "$method" in
PUT|DELETE|PATCH)
echo "ERROR: la skill 'bitwarden' bloquea $method (read+create only)." >&2
echo " Si REALMENTE necesitás modificar/eliminar, usá bw CLI directo:" >&2
echo " BITWARDENCLI_APPDATA_DIR=$SKILL_DIR/.cache/bw \\" >&2
echo " BW_SESSION=\$(cat $SKILL_DIR/.cache/session) bw <cmd>" >&2
exit 3
;;
POST)
# Path base sin querystring
base_path="${path%%\?*}"
case "$base_path" in
/object/item|/object/folder|/object/send|/object/org-collection)
;; # create permitido
/sync|/unlock|/lock|/generate)
;; # auth/utility permitidos
*)
echo "ERROR: POST $base_path bloqueado por la skill." >&2
echo " POST permitido sólo en: /object/item, /object/folder, /object/send," >&2
echo " /object/org-collection, /sync, /unlock, /lock, /generate." >&2
echo " Endpoints como /move, /restore, /confirm, /object/attachment" >&2
echo " están bloqueados (modifican estado existente)." >&2
exit 3
;;
esac
;;
esac
# ─── Asegurar bw serve arriba ───────────────────────────────────────────
"$SKILL_DIR/scripts/serve-up.sh" >/dev/null
# ─── Llamar ─────────────────────────────────────────────────────────────
exec curl -sS \
-H "Accept: application/json" \
"${args[@]}" \
"${BASE}${path}"