#!/bin/bash # Generic API wrapper using Vault for dynamic token retrieval # Supports multiple auth header types # Usage: bash vault_api.sh [header_type] [payload_file] # Examples: # bash vault_api.sh GET "https://grist.beawit.net" "/api/..." "api/integration/grist" "Bearer" # bash vault_api.sh GET "http://192.168.25.5:8080" "/api/..." "api/integration/nocodb" "xc-token" TOKEN_DIR="/home/jcbeasley/.openclaw/workspace/.tokens" VAULT_URL="https://beavault.beawit.net:8200" METHOD="$1" BASE_URL="$2" API_PATH="$3" VAULT_KEY="***" HEADER_TYPE="${5:-Bearer}" PAYLOAD_FILE="$6" if [ -z "$METHOD" ] || [ -z "$BASE_URL" ] || [ -z "$API_PATH" ] || [ -z "$VAULT_KEY" ]; then echo "Usage: bash vault_api.sh [header_type] [payload_file]" echo "Header types: Bearer (default), xc-token, api-key, X-Api-Key, X-Vault-Token" echo "Example: bash vault_api.sh GET 'https://grist.beawit.net' '/api/...' 'api/integration/grist' 'Bearer'" exit 1 fi mkdir -p "$TOKEN_DIR" # Function to get Vault token cache_vault_token() { local cached_token="$TOKEN_DIR/vault_session_token" if [ -f "$cached_token" ]; then local test_resp test_resp=$(curl -sk -H "X-Vault-Token: $(cat $cached_token)" "$VAULT_URL/v1/sys/health" 2>/dev/null) if [ -n "$test_resp" ]; then cat "$cached_token" return 0 fi fi curl -sk -X POST \ -d '{"role_id":"75d2dcfb-9c65-7f60-59b4-eee8c7f8dc0e","secret_id":"6202b465-2f25-547c-ec07-f47cfc4dda3e"}' \ "$VAULT_URL/v1/auth/approle/login" > "$TOKEN_DIR/vault_auth.json" python3 -c " import json with open('$TOKEN_DIR/vault_auth.json') as f: data = json.load(f) with open('$cached_token', 'w') as out: out.write(data['auth']['client_token']) " rm -f "$TOKEN_DIR/vault_auth.json" cat "$cached_token" } # Function to get service token cache_service_token() { local vault_token="$1" local vault_key="$2" local cache_file="$TOKEN_DIR/service_$(echo "$vault_key" | tr '/' '_').token" if [ -f "$cache_file" ]; then local age age=$(($(date +%s) - $(stat -c %Y "$cache_file"))) if [ "$age" -lt 3600 ]; then cat "$cache_file" return 0 fi fi curl -sk -H "X-Vault-Token: $vault_token" \ "$VAULT_URL/v1/kv/data/$vault_key" > "$TOKEN_DIR/service_resp.json" python3 -c " import json with open('$TOKEN_DIR/service_resp.json') as f: data = json.load(f) token = data['data']['data']['token'] with open('$cache_file', 'w') as out: out.write(token) " rm -f "$TOKEN_DIR/service_resp.json" cat "$cache_file" } # Build auth header based on type build_auth_header() { local header_type="$1" local token="$2" case "$header_type" in "xc-token") echo "xc-token: $token" ;; "api-key"|"API-Key") echo "API-Key: $token" ;; "X-Api-Key"|"x-api-key") echo "X-Api-Key: $token" ;; "X-Vault-Token"|"vault") echo "X-Vault-Token: $token" ;; "Bearer"|*) echo "Authorization: Bearer $token" ;; esac } # Main logic VAULT_TOKEN=$(cache_vault_token) SERVICE_TOKEN=$(cache_service_token "$VAULT_TOKEN" "$VAULT_KEY") AUTH_HEADER=$(build_auth_header "$HEADER_TYPE" "$SERVICE_TOKEN") URL="${BASE_URL}${API_PATH}" RESPONSE_FILE="$TOKEN_DIR/last_response.json" # Execute API call if [ "$METHOD" = "GET" ]; then curl -sk -w "\nHTTP_CODE:%{http_code}" \ -H "$AUTH_HEADER" \ -H "Content-Type: application/json" \ -o "$RESPONSE_FILE" \ "$URL" elif [ "$METHOD" = "PATCH" ] && [ -n "$PAYLOAD_FILE" ]; then curl -sk -w "\nHTTP_CODE:%{http_code}" \ -H "$AUTH_HEADER" \ -H "Content-Type: application/json" \ -X PATCH \ -d "@$PAYLOAD_FILE" \ -o "$RESPONSE_FILE" \ "$URL" elif [ "$METHOD" = "POST" ] && [ -n "$PAYLOAD_FILE" ]; then curl -sk -w "\nHTTP_CODE:%{http_code}" \ -H "$AUTH_HEADER" \ -H "Content-Type: application/json" \ -X POST \ -d "@$PAYLOAD_FILE" \ -o "$RESPONSE_FILE" \ "$URL" else echo "Error: Unsupported method or missing payload file" exit 1 fi # Output response cat "$RESPONSE_FILE" rm -f "$RESPONSE_FILE"