Files
openclaw-bms/scripts/bms-auth.sh

135 lines
4.8 KiB
Bash
Executable File

#!/usr/bin/env bash
# bms-auth.sh — Kaseya BMS authentication helper
# Obtains and caches JWT tokens. Called by bms.sh.
set -euo pipefail
BMS_API_BASE="${BMS_API_BASE:-https://api.bms.kaseya.com}"
BMS_TOKEN_FILE="${BMS_TOKEN_FILE:-$HOME/.bms_token.json}"
# ─── Helpers ────────────────────────────────────────────────────────────────
die() { echo "ERROR: $*" >&2; exit 1; }
require_env() {
local var="$1"
[[ -n "${!var:-}" ]] || die "Environment variable $var is required. See SKILL.md for setup."
}
token_is_valid() {
# Returns 0 (true) if cached token exists and has not expired (with 60s buffer)
[[ -f "$BMS_TOKEN_FILE" ]] || return 1
local exp
exp=$(jq -r '.expires_at // 0' "$BMS_TOKEN_FILE" 2>/dev/null) || return 1
local now
now=$(date +%s)
[[ $((exp - 60)) -gt $now ]]
}
save_token() {
local response="$1"
local access_token refresh_token expires_in expires_at
access_token=$(echo "$response" | jq -r '.AccessToken // .access_token // empty')
refresh_token=$(echo "$response" | jq -r '.RefreshToken // .refresh_token // empty')
expires_in=$(echo "$response" | jq -r '.ExpiresIn // .expires_in // 3600')
expires_at=$(( $(date +%s) + expires_in ))
[[ -n "$access_token" ]] || die "No access token in auth response: $response"
jq -n \
--arg at "$access_token" \
--arg rt "${refresh_token:-}" \
--argjson ea "$expires_at" \
'{access_token: $at, refresh_token: $rt, expires_at: $ea}' \
> "$BMS_TOKEN_FILE"
chmod 600 "$BMS_TOKEN_FILE"
}
# ─── Auth Actions ────────────────────────────────────────────────────────────
cmd_auth_login() {
require_env BMS_TENANT
local response
if [[ -n "${BMS_CLIENT_ID:-}" && -n "${BMS_CLIENT_SECRET:-}" ]]; then
# OAuth2 client credentials flow
echo "Authenticating with client credentials..." >&2
response=$(curl -sf -X POST "${BMS_API_BASE}/v2/security/authenticate" \
-F "GrantType=client_credentials" \
-F "ClientId=${BMS_CLIENT_ID}" \
-F "ClientSecret=${BMS_CLIENT_SECRET}" \
-F "Tenant=${BMS_TENANT}") || die "Authentication request failed"
else
# Password flow
require_env BMS_USERNAME
require_env BMS_PASSWORD
echo "Authenticating with username/password..." >&2
response=$(curl -sf -X POST "${BMS_API_BASE}/v2/security/authenticate" \
-F "GrantType=password" \
-F "UserName=${BMS_USERNAME}" \
-F "Password=${BMS_PASSWORD}" \
-F "Tenant=${BMS_TENANT}") || die "Authentication request failed"
fi
save_token "$response"
echo "Authenticated successfully. Token cached at $BMS_TOKEN_FILE" >&2
}
cmd_auth_refresh() {
[[ -f "$BMS_TOKEN_FILE" ]] || die "No cached token. Run: bms auth"
local access_token refresh_token
access_token=$(jq -r '.access_token' "$BMS_TOKEN_FILE")
refresh_token=$(jq -r '.refresh_token // empty' "$BMS_TOKEN_FILE")
[[ -n "$refresh_token" ]] || { cmd_auth_login; return; }
local response
response=$(curl -sf -X POST "${BMS_API_BASE}/v2/security/refreshtoken" \
-H "Content-Type: application/json" \
-d "{\"AccessToken\":\"${access_token}\",\"RefreshToken\":\"${refresh_token}\"}") \
|| { echo "Refresh failed, re-authenticating..." >&2; cmd_auth_login; return; }
save_token "$response"
echo "Token refreshed." >&2
}
cmd_auth_status() {
if [[ ! -f "$BMS_TOKEN_FILE" ]]; then
echo "No token cached."
return
fi
local expires_at now remaining
expires_at=$(jq -r '.expires_at // 0' "$BMS_TOKEN_FILE")
now=$(date +%s)
remaining=$((expires_at - now))
if [[ $remaining -gt 0 ]]; then
echo "Token valid. Expires in ${remaining}s (at $(date -d "@${expires_at}" 2>/dev/null || date -r "${expires_at}" 2>/dev/null || echo "unknown"))"
else
echo "Token expired ${remaining#-}s ago."
fi
}
# ─── Public: get_token ───────────────────────────────────────────────────────
# Prints the current access token, refreshing/authenticating as needed.
get_token() {
if ! token_is_valid; then
if [[ -f "$BMS_TOKEN_FILE" ]]; then
cmd_auth_refresh
else
cmd_auth_login
fi
fi
jq -r '.access_token' "$BMS_TOKEN_FILE"
}
# ─── Dispatch ────────────────────────────────────────────────────────────────
case "${1:-}" in
login|"") cmd_auth_login ;;
refresh) cmd_auth_refresh ;;
status) cmd_auth_status ;;
get-token) get_token ;;
*) echo "Usage: bms-auth.sh [login|refresh|status|get-token]" >&2; exit 1 ;;
esac