Add .bms-actions logging (partial): auth login/refresh, create, note, delete. Need: update, assign, resolve.
This commit is contained in:
17
scripts/bms-auth.sh
Executable file → Normal file
17
scripts/bms-auth.sh
Executable file → Normal file
@@ -4,6 +4,10 @@
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Import logging
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
source "${SCRIPT_DIR}/bms-logging.sh"
|
||||
|
||||
BMS_API_BASE="${BMS_API_BASE:-https://api.bms.kaseya.com}"
|
||||
BMS_TOKEN_FILE="${BMS_TOKEN_FILE:-$HOME/.bms_token.json}"
|
||||
|
||||
@@ -76,6 +80,15 @@ cmd_auth_login() {
|
||||
|
||||
save_token "$response"
|
||||
echo "Authenticated successfully. Token cached at $BMS_TOKEN_FILE" >&2
|
||||
|
||||
# Log successful login
|
||||
local args_json
|
||||
args_json=$(jq -n \
|
||||
--arg tenant "${BMS_TENANT}" \
|
||||
--arg username "${BMS_USERNAME}" \
|
||||
'{"tenant": $tenant, "username": $username}')
|
||||
local result_json='{"success": true}'
|
||||
log_action "auth.login" "$args_json" "$result_json" "success"
|
||||
}
|
||||
|
||||
cmd_auth_refresh() {
|
||||
@@ -94,6 +107,10 @@ cmd_auth_refresh() {
|
||||
|
||||
save_token "$response"
|
||||
echo "Token refreshed." >&2
|
||||
|
||||
# Log token refresh
|
||||
local result_json='{"success": true}'
|
||||
log_action "auth.refresh" "{}" "$result_json" "success"
|
||||
}
|
||||
|
||||
cmd_auth_status() {
|
||||
|
||||
59
scripts/bms-logging.sh
Executable file
59
scripts/bms-logging.sh
Executable file
@@ -0,0 +1,59 @@
|
||||
#!/usr/bin/env bash
|
||||
# bms-logging.sh — Action logging for BMS skill
|
||||
# Centralized logging of user-initiated actions for audit/review
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
# Log directory (can be overridden)
|
||||
BMS_LOG_DIR="${BMS_LOG_DIR:-$HOME/.bms-actions}"
|
||||
|
||||
# Ensure log directory exists
|
||||
mkdir -p "$BMS_LOG_DIR"
|
||||
|
||||
# Current log file (by date, UTC)
|
||||
BMS_LOG_FILE="$BMS_LOG_DIR/$(date -u +%Y-%m-%d).jsonl"
|
||||
|
||||
# Sanitize arguments: strip any sensitive values from a JSON object
|
||||
# Usage: sanitized=$(sanitize_args '{"password":"secret","token":"abc"}')
|
||||
sanitize_args() {
|
||||
local input="$1"
|
||||
# Remove known sensitive keys; preserve structure
|
||||
jq 'del(.["BMS_PASSWORD"], .["BMS_MFA_CODE"], .["BMS_CLIENT_SECRET"], .["access_token"], .["refresh_token"], .["token"], .["Authorization"])' 2>/dev/null <<<"$input" || echo "$input"
|
||||
}
|
||||
|
||||
# Log an action
|
||||
# Arguments: command, args_json, result_json, status (success|error)
|
||||
log_action() {
|
||||
local command="$1"
|
||||
local args_json="${2:-{}}"
|
||||
local result_json="${3:-{}}"
|
||||
local status="${4:-success}"
|
||||
|
||||
local timestamp
|
||||
timestamp=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
||||
|
||||
# Sanitize args and result
|
||||
local safe_args safe_result
|
||||
safe_args=$(sanitize_args "$args_json")
|
||||
safe_result=$(sanitize_args "$result_json")
|
||||
|
||||
# Build log entry as single JSON line
|
||||
local entry
|
||||
entry=$(jq -n \
|
||||
--arg ts "$timestamp" \
|
||||
--arg cmd "$command" \
|
||||
--argjson args "$safe_args" \
|
||||
--argjson result "$safe_result" \
|
||||
--arg stat "$status" \
|
||||
'{timestamp: $ts, command: $cmd, args: $args, result: $result, status: $stat}')
|
||||
|
||||
# Append atomically
|
||||
echo "$entry" >> "$BMS_LOG_FILE"
|
||||
}
|
||||
|
||||
# Get current log file path
|
||||
get_log_path() {
|
||||
echo "$BMS_LOG_FILE"
|
||||
}
|
||||
81
scripts/bms-tickets.sh
Executable file → Normal file
81
scripts/bms-tickets.sh
Executable file → Normal file
@@ -3,7 +3,10 @@
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Import logging
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
source "${SCRIPT_DIR}/bms-logging.sh"
|
||||
|
||||
BMS_API_BASE="${BMS_API_BASE:-https://api.bms.kaseya.com}"
|
||||
|
||||
# ─── Helpers ─────────────────────────────────────────────────────────────────
|
||||
@@ -272,10 +275,43 @@ cmd_create() {
|
||||
if [[ "$success" != "true" ]] || [[ -z "$ticket_id" ]] || [[ "$ticket_id" == "null" ]]; then
|
||||
echo "Create ticket failed or returned ambiguous response:" >&2
|
||||
echo "$response" | jq . >&2
|
||||
# Log failure
|
||||
local args_json result_json
|
||||
args_json=$(jq -n \
|
||||
--arg title "$title" \
|
||||
--arg details "$details" \
|
||||
--argjson account_id "$account_id" \
|
||||
--argjson location_id "$location_id" \
|
||||
--argjson status_id "$status_id" \
|
||||
--argjson priority_id "$priority_id" \
|
||||
--argjson type_id "$type_id" \
|
||||
--argjson source_id "$source_id" \
|
||||
--argjson queue_id "${queue_id:-null}" \
|
||||
--argjson assignee_id "${assignee_id:-null}" \
|
||||
'{title: $title, details: $details, account_id: $account_id, location_id: $location_id, status_id: $status_id, priority_id: $priority_id, type_id: $type_id, source_id: $source_id, queue_id: $queue_id, assignee_id: $assignee_id}')
|
||||
result_json=$(jq -n '{error: "creation_failed", response: ("$response" | fromjson? // "$response")}')
|
||||
log_action "tickets.create" "$args_json" "$result_json" "error"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Created ticket ID: ${ticket_id} — ${ticket_number:-N/A}"
|
||||
# Log success
|
||||
local args_json result_json
|
||||
args_json=$(jq -n \
|
||||
--arg title "$title" \
|
||||
--arg details "$details" \
|
||||
--argjson account_id "$account_id" \
|
||||
--argjson location_id "$location_id" \
|
||||
--argjson status_id "$status_id" \
|
||||
--argjson priority_id "$priority_id" \
|
||||
--argjson type_id "$type_id" \
|
||||
--argjson source_id "$source_id" \
|
||||
--argjson queue_id "${queue_id:-null}" \
|
||||
--argjson assignee_id "${assignee_id:-null}" \
|
||||
'{title: $title, details: $details, account_id: $account_id, location_id: $location_id, status_id: $status_id, priority_id: $priority_id, type_id: $type_id, source_id: $source_id, queue_id: $queue_id, assignee_id: $assignee_id}')
|
||||
result_json=$(jq -n --argjson tid "$ticket_id" --arg tn "${ticket_number:-}" '{ticket_id: $tid, ticket_number: $tn}')
|
||||
log_action "tickets.create" "$args_json" "$result_json" "success"
|
||||
|
||||
}
|
||||
|
||||
cmd_update() {
|
||||
@@ -362,7 +398,25 @@ cmd_note() {
|
||||
|
||||
local response
|
||||
response=$(bms_curl POST "/v2/servicedesk/tickets/${ticket_id}/notes" -d "$body")
|
||||
echo "$response" | jq -r '"Note added (ID: \(.Data.Id // .Id // "ok"))"'
|
||||
local note_id
|
||||
note_id=$(echo "$response" | jq -r '.Data.Id // .Id // empty')
|
||||
if [[ -z "$note_id" || "$note_id" == "null" ]]; then
|
||||
echo "Note add failed or returned ambiguous response:" >&2
|
||||
echo "$response" | jq . >&2
|
||||
# Log failure
|
||||
local args_json result_json
|
||||
args_json=$(jq -n --argjson ticket_id "$ticket_id" --arg message "$message" --argjson type_id "$type_id" '{ticket_id: $ticket_id, message: $message, type_id: $type_id}')
|
||||
result_json=$(jq -n '{error: "note_add_failed", response: ("$response" | fromjson? // "$response")}')
|
||||
log_action "tickets.note" "$args_json" "$result_json" "error"
|
||||
exit 1
|
||||
fi
|
||||
echo "Note added (ID: ${note_id})"
|
||||
# Log success
|
||||
local args_json result_json
|
||||
args_json=$(jq -n --argjson ticket_id "$ticket_id" --arg message "$message" --argjson type_id "$type_id" '{ticket_id: $ticket_id, message: $message, type_id: $type_id}')
|
||||
result_json=$(jq -n --argjson note_id "$note_id" '{note_id: $note_id}')
|
||||
log_action "tickets.note" "$args_json" "$result_json" "success"
|
||||
|
||||
}
|
||||
|
||||
cmd_assign() {
|
||||
@@ -447,15 +501,36 @@ cmd_delete() {
|
||||
local ids=("$@")
|
||||
[[ ${#ids[@]} -gt 0 ]] || die "Usage: bms tickets delete <id> [id2 ...]"
|
||||
|
||||
local response=""
|
||||
if [[ ${#ids[@]} -eq 1 ]]; then
|
||||
bms_curl DELETE "/v2/servicedesk/tickets/${ids[0]}" >/dev/null
|
||||
response=$(bms_curl DELETE "/v2/servicedesk/tickets/${ids[0]}")
|
||||
echo "Deleted ticket ${ids[0]}"
|
||||
else
|
||||
local body
|
||||
body=$(printf '%s\n' "${ids[@]}" | jq -Rs 'split("\n") | map(select(. != "")) | map(tonumber) | {Ids: .}')
|
||||
bms_curl DELETE "/v2/servicedesk/tickets" -d "$body" >/dev/null
|
||||
response=$(bms_curl DELETE "/v2/servicedesk/tickets" -d "$body")
|
||||
echo "Deleted tickets: ${ids[*]}"
|
||||
fi
|
||||
|
||||
# Check success (DELETE often returns { success: true } or empty)
|
||||
local success
|
||||
success=$(echo "$response" | jq -r '.success // .Success // ""')
|
||||
if [[ "$success" != "true" ]] && [[ -n "$response" ]] && echo "$response" | jq -e . >/dev/null 2>&1; then
|
||||
# If response is JSON but not success=true, treat as failure
|
||||
echo "Delete operation may have failed:" >&2
|
||||
echo "$response" | jq . >&2
|
||||
local args_json result_json
|
||||
args_json=$(jq -n --argjson ids "${ids}" '{ids: $ids}')
|
||||
result_json=$(jq -n '{error: "delete_failed", response: ("$response" | fromjson? // "$response")}')
|
||||
log_action "tickets.delete" "$args_json" "$result_json" "error"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Log success
|
||||
local args_json result_json
|
||||
args_json=$(jq -n --argjson ids "${ids}" '{ids: $ids}')
|
||||
result_json=$(jq -n --argjson deleted_ids "${ids}" '{deleted_ids: $deleted_ids}')
|
||||
log_action "tickets.delete" "$args_json" "$result_json" "success"
|
||||
}
|
||||
|
||||
# ─── Dispatch ────────────────────────────────────────────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user