366 lines
11 KiB
Bash
366 lines
11 KiB
Bash
#!/usr/bin/env bash
|
||
# =====================================================
|
||
# Installer JSON API Test Script
|
||
# =====================================================
|
||
# Tests all API endpoints and verifies functionality
|
||
|
||
set -Eeuo pipefail
|
||
|
||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
|
||
# Source libraries
|
||
source "${SCRIPT_DIR}/libsupabase.sh"
|
||
source "${SCRIPT_DIR}/lib_installer_json_api.sh"
|
||
|
||
# Colors for output
|
||
RED='\033[0;31m'
|
||
GREEN='\033[0;32m'
|
||
YELLOW='\033[1;33m'
|
||
BLUE='\033[0;34m'
|
||
NC='\033[0m' # No Color
|
||
|
||
# Test counters
|
||
TESTS_PASSED=0
|
||
TESTS_FAILED=0
|
||
TESTS_TOTAL=0
|
||
|
||
# Test configuration
|
||
TEST_CTID="${TEST_CTID:-769697636}"
|
||
TEST_EMAIL="${TEST_EMAIL:-test@example.com}"
|
||
TEST_POSTGREST_URL="${TEST_POSTGREST_URL:-http://192.168.45.104:3000}"
|
||
TEST_SERVICE_ROLE_KEY="${TEST_SERVICE_ROLE_KEY:-}"
|
||
|
||
# Usage
|
||
usage() {
|
||
cat <<EOF
|
||
Usage: bash test_installer_json_api.sh [options]
|
||
|
||
Options:
|
||
--ctid <id> Test CTID (default: 769697636)
|
||
--email <email> Test email (default: test@example.com)
|
||
--postgrest-url <url> PostgREST URL (default: http://192.168.45.104:3000)
|
||
--service-role-key <key> Service role key for authenticated tests
|
||
--help Show this help
|
||
|
||
Examples:
|
||
# Basic test (public endpoints only)
|
||
bash test_installer_json_api.sh
|
||
|
||
# Full test with authentication
|
||
bash test_installer_json_api.sh --service-role-key "eyJhbGc..."
|
||
|
||
# Test specific instance
|
||
bash test_installer_json_api.sh --ctid 769697636 --email max@beispiel.de
|
||
EOF
|
||
}
|
||
|
||
# Parse arguments
|
||
while [[ $# -gt 0 ]]; do
|
||
case "$1" in
|
||
--ctid) TEST_CTID="${2:-}"; shift 2 ;;
|
||
--email) TEST_EMAIL="${2:-}"; shift 2 ;;
|
||
--postgrest-url) TEST_POSTGREST_URL="${2:-}"; shift 2 ;;
|
||
--service-role-key) TEST_SERVICE_ROLE_KEY="${2:-}"; shift 2 ;;
|
||
--help|-h) usage; exit 0 ;;
|
||
*) echo "Unknown option: $1"; usage; exit 1 ;;
|
||
esac
|
||
done
|
||
|
||
# Print functions
|
||
print_header() {
|
||
echo -e "\n${BLUE}========================================${NC}"
|
||
echo -e "${BLUE}$1${NC}"
|
||
echo -e "${BLUE}========================================${NC}\n"
|
||
}
|
||
|
||
print_test() {
|
||
echo -e "${YELLOW}TEST $((TESTS_TOTAL + 1)):${NC} $1"
|
||
}
|
||
|
||
print_pass() {
|
||
echo -e "${GREEN}✓ PASS${NC}: $1"
|
||
((TESTS_PASSED++))
|
||
((TESTS_TOTAL++))
|
||
}
|
||
|
||
print_fail() {
|
||
echo -e "${RED}✗ FAIL${NC}: $1"
|
||
((TESTS_FAILED++))
|
||
((TESTS_TOTAL++))
|
||
}
|
||
|
||
print_skip() {
|
||
echo -e "${YELLOW}⊘ SKIP${NC}: $1"
|
||
}
|
||
|
||
print_info() {
|
||
echo -e "${BLUE}ℹ INFO${NC}: $1"
|
||
}
|
||
|
||
# Test functions
|
||
|
||
test_api_connectivity() {
|
||
print_test "API Connectivity"
|
||
|
||
local response
|
||
local http_code
|
||
|
||
response=$(curl -sS -w "\n%{http_code}" -X POST "${TEST_POSTGREST_URL}/rpc/get_public_config" \
|
||
-H "Content-Type: application/json" \
|
||
-d '{}' 2>&1 || echo -e "\nFAILED")
|
||
|
||
http_code=$(echo "$response" | tail -n1)
|
||
|
||
if [[ "$http_code" == "200" ]]; then
|
||
print_pass "API is reachable (HTTP 200)"
|
||
else
|
||
print_fail "API is not reachable (HTTP ${http_code})"
|
||
fi
|
||
}
|
||
|
||
test_public_config() {
|
||
print_test "Get Public Config"
|
||
|
||
local response
|
||
response=$(get_public_config "${TEST_POSTGREST_URL}" 2>/dev/null || echo "")
|
||
|
||
if [[ -n "$response" ]]; then
|
||
# Check if response contains expected fields
|
||
if echo "$response" | grep -q "registration_webhook_url"; then
|
||
print_pass "Public config retrieved successfully"
|
||
print_info "Response: ${response}"
|
||
else
|
||
print_fail "Public config missing expected fields"
|
||
fi
|
||
else
|
||
print_fail "Failed to retrieve public config"
|
||
fi
|
||
}
|
||
|
||
test_get_instance_by_email() {
|
||
print_test "Get Instance Config by Email"
|
||
|
||
local response
|
||
response=$(get_installer_json_by_email "${TEST_EMAIL}" "${TEST_POSTGREST_URL}" 2>/dev/null || echo "")
|
||
|
||
if [[ -n "$response" && "$response" != "[]" ]]; then
|
||
# Check if response contains expected fields
|
||
if echo "$response" | grep -q "ctid"; then
|
||
print_pass "Instance config retrieved by email"
|
||
|
||
# Verify no secrets are exposed
|
||
if echo "$response" | grep -qE "password|service_role_key|jwt_secret|encryption_key"; then
|
||
print_fail "Response contains secrets (SECURITY ISSUE!)"
|
||
else
|
||
print_pass "No secrets exposed in response"
|
||
fi
|
||
|
||
# Print sample of response
|
||
local ctid
|
||
ctid=$(echo "$response" | python3 -c "import json,sys; d=json.load(sys.stdin); print(d[0]['ctid'] if d else 'N/A')" 2>/dev/null || echo "N/A")
|
||
print_info "Found CTID: ${ctid}"
|
||
else
|
||
print_fail "Instance config missing expected fields"
|
||
fi
|
||
else
|
||
print_skip "No instance found for email: ${TEST_EMAIL} (this is OK if instance doesn't exist)"
|
||
fi
|
||
}
|
||
|
||
test_get_instance_by_ctid() {
|
||
print_test "Get Instance Config by CTID (requires service role key)"
|
||
|
||
if [[ -z "$TEST_SERVICE_ROLE_KEY" ]]; then
|
||
print_skip "Service role key not provided (use --service-role-key)"
|
||
return
|
||
fi
|
||
|
||
local response
|
||
response=$(get_installer_json_by_ctid "${TEST_CTID}" "${TEST_POSTGREST_URL}" "${TEST_SERVICE_ROLE_KEY}" 2>/dev/null || echo "")
|
||
|
||
if [[ -n "$response" && "$response" != "[]" ]]; then
|
||
# Check if response contains expected fields
|
||
if echo "$response" | grep -q "ctid"; then
|
||
print_pass "Instance config retrieved by CTID"
|
||
|
||
# Verify no secrets are exposed
|
||
if echo "$response" | grep -qE "password|service_role_key|jwt_secret|encryption_key"; then
|
||
print_fail "Response contains secrets (SECURITY ISSUE!)"
|
||
else
|
||
print_pass "No secrets exposed in response"
|
||
fi
|
||
else
|
||
print_fail "Instance config missing expected fields"
|
||
fi
|
||
else
|
||
print_skip "No instance found for CTID: ${TEST_CTID} (this is OK if instance doesn't exist)"
|
||
fi
|
||
}
|
||
|
||
test_store_installer_json() {
|
||
print_test "Store Installer JSON (requires service role key)"
|
||
|
||
if [[ -z "$TEST_SERVICE_ROLE_KEY" ]]; then
|
||
print_skip "Service role key not provided (use --service-role-key)"
|
||
return
|
||
fi
|
||
|
||
# Create test JSON
|
||
local test_json
|
||
test_json=$(cat <<EOF
|
||
{
|
||
"ctid": ${TEST_CTID},
|
||
"hostname": "sb-${TEST_CTID}",
|
||
"fqdn": "sb-${TEST_CTID}.userman.de",
|
||
"ip": "192.168.45.104",
|
||
"vlan": 90,
|
||
"urls": {
|
||
"n8n_internal": "http://192.168.45.104:5678/",
|
||
"n8n_external": "https://sb-${TEST_CTID}.userman.de",
|
||
"postgrest": "http://192.168.45.104:3000",
|
||
"chat_webhook": "https://sb-${TEST_CTID}.userman.de/webhook/rag-chat-webhook/chat",
|
||
"chat_internal": "http://192.168.45.104:5678/webhook/rag-chat-webhook/chat",
|
||
"upload_form": "https://sb-${TEST_CTID}.userman.de/form/rag-upload-form",
|
||
"upload_form_internal": "http://192.168.45.104:5678/form/rag-upload-form"
|
||
},
|
||
"postgres": {
|
||
"host": "postgres",
|
||
"port": 5432,
|
||
"db": "customer",
|
||
"user": "customer",
|
||
"password": "TEST_PASSWORD_SHOULD_NOT_BE_EXPOSED"
|
||
},
|
||
"supabase": {
|
||
"url": "http://postgrest:3000",
|
||
"url_external": "http://192.168.45.104:3000",
|
||
"anon_key": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.TEST",
|
||
"service_role_key": "TEST_SERVICE_ROLE_KEY_SHOULD_NOT_BE_EXPOSED",
|
||
"jwt_secret": "TEST_JWT_SECRET_SHOULD_NOT_BE_EXPOSED"
|
||
},
|
||
"ollama": {
|
||
"url": "http://192.168.45.3:11434",
|
||
"model": "ministral-3:3b",
|
||
"embedding_model": "nomic-embed-text:latest"
|
||
},
|
||
"n8n": {
|
||
"encryption_key": "TEST_ENCRYPTION_KEY_SHOULD_NOT_BE_EXPOSED",
|
||
"owner_email": "admin@userman.de",
|
||
"owner_password": "TEST_PASSWORD_SHOULD_NOT_BE_EXPOSED",
|
||
"secure_cookie": false
|
||
}
|
||
}
|
||
EOF
|
||
)
|
||
|
||
# Try to store
|
||
if store_installer_json_in_db "${TEST_CTID}" "${TEST_EMAIL}" "${TEST_POSTGREST_URL}" "${TEST_SERVICE_ROLE_KEY}" "${test_json}"; then
|
||
print_pass "Installer JSON stored successfully"
|
||
|
||
# Verify it was stored
|
||
sleep 1
|
||
local response
|
||
response=$(get_installer_json_by_email "${TEST_EMAIL}" "${TEST_POSTGREST_URL}" 2>/dev/null || echo "")
|
||
|
||
if [[ -n "$response" && "$response" != "[]" ]]; then
|
||
print_pass "Stored data can be retrieved"
|
||
|
||
# Verify secrets are NOT in the response
|
||
if echo "$response" | grep -q "TEST_PASSWORD_SHOULD_NOT_BE_EXPOSED"; then
|
||
print_fail "CRITICAL: Passwords are exposed in API response!"
|
||
elif echo "$response" | grep -q "TEST_SERVICE_ROLE_KEY_SHOULD_NOT_BE_EXPOSED"; then
|
||
print_fail "CRITICAL: Service role key is exposed in API response!"
|
||
elif echo "$response" | grep -q "TEST_JWT_SECRET_SHOULD_NOT_BE_EXPOSED"; then
|
||
print_fail "CRITICAL: JWT secret is exposed in API response!"
|
||
elif echo "$response" | grep -q "TEST_ENCRYPTION_KEY_SHOULD_NOT_BE_EXPOSED"; then
|
||
print_fail "CRITICAL: Encryption key is exposed in API response!"
|
||
else
|
||
print_pass "SECURITY: All secrets are properly filtered"
|
||
fi
|
||
else
|
||
print_fail "Stored data could not be retrieved"
|
||
fi
|
||
else
|
||
print_skip "Failed to store installer JSON (instance may not exist in database)"
|
||
fi
|
||
}
|
||
|
||
test_cors_headers() {
|
||
print_test "CORS Headers"
|
||
|
||
local response
|
||
response=$(curl -sS -I -X OPTIONS "${TEST_POSTGREST_URL}/rpc/get_public_config" \
|
||
-H "Origin: https://botkonzept.de" \
|
||
-H "Access-Control-Request-Method: POST" 2>&1 || echo "")
|
||
|
||
if echo "$response" | grep -qi "access-control-allow-origin"; then
|
||
print_pass "CORS headers are present"
|
||
else
|
||
print_skip "CORS headers not found (may need configuration)"
|
||
fi
|
||
}
|
||
|
||
test_rate_limiting() {
|
||
print_test "Rate Limiting (optional)"
|
||
|
||
print_skip "Rate limiting test not implemented (should be configured at nginx/gateway level)"
|
||
}
|
||
|
||
test_response_format() {
|
||
print_test "Response Format Validation"
|
||
|
||
local response
|
||
response=$(get_public_config "${TEST_POSTGREST_URL}" 2>/dev/null || echo "")
|
||
|
||
if [[ -n "$response" ]]; then
|
||
# Validate JSON format
|
||
if echo "$response" | python3 -m json.tool >/dev/null 2>&1; then
|
||
print_pass "Response is valid JSON"
|
||
else
|
||
print_fail "Response is not valid JSON"
|
||
fi
|
||
else
|
||
print_fail "No response received"
|
||
fi
|
||
}
|
||
|
||
# Main test execution
|
||
main() {
|
||
print_header "BotKonzept Installer JSON API Tests"
|
||
|
||
echo "Test Configuration:"
|
||
echo " CTID: ${TEST_CTID}"
|
||
echo " Email: ${TEST_EMAIL}"
|
||
echo " PostgREST URL: ${TEST_POSTGREST_URL}"
|
||
echo " Service Role Key: ${TEST_SERVICE_ROLE_KEY:+***provided***}"
|
||
echo ""
|
||
|
||
# Run tests
|
||
test_api_connectivity
|
||
test_public_config
|
||
test_response_format
|
||
test_cors_headers
|
||
test_get_instance_by_email
|
||
test_get_instance_by_ctid
|
||
test_store_installer_json
|
||
test_rate_limiting
|
||
|
||
# Print summary
|
||
print_header "Test Summary"
|
||
|
||
echo "Total Tests: ${TESTS_TOTAL}"
|
||
echo -e "${GREEN}Passed: ${TESTS_PASSED}${NC}"
|
||
echo -e "${RED}Failed: ${TESTS_FAILED}${NC}"
|
||
echo ""
|
||
|
||
if [[ $TESTS_FAILED -eq 0 ]]; then
|
||
echo -e "${GREEN}✓ All tests passed!${NC}"
|
||
exit 0
|
||
else
|
||
echo -e "${RED}✗ Some tests failed${NC}"
|
||
exit 1
|
||
fi
|
||
}
|
||
|
||
# Run main
|
||
main
|