#!/bin/bash # SiriusScan Integration Test Script # Tests service integration and end-to-end functionality set -e # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # Configuration SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # Check if we're in container-testing directory or testing directory if [[ "$SCRIPT_DIR" == *"/container-testing" ]]; then PROJECT_ROOT="$(dirname "$(dirname "$SCRIPT_DIR")")" else PROJECT_ROOT="$(dirname "$SCRIPT_DIR")" fi LOG_DIR="$PROJECT_ROOT/testing/logs" TIMESTAMP=$(date +"%Y%m%d_%H%M%S") LOG_FILE="$LOG_DIR/integration_test_$TIMESTAMP.log" # Required compose variables for strict startup contract. export POSTGRES_PASSWORD="${POSTGRES_PASSWORD:-test-postgres-password}" export NEXTAUTH_SECRET="${NEXTAUTH_SECRET:-test-nextauth-secret}" export INITIAL_ADMIN_PASSWORD="${INITIAL_ADMIN_PASSWORD:-test-admin-password}" INTERNAL_API_KEY_TEST_VALUE="${SIRIUS_INTERNAL_API_KEY_TEST_VALUE:-test-api-key}" # Environment variables for configuration TEST_TIMEOUT="${TEST_TIMEOUT:-60}" # Default 60 seconds TEST_RETRIES="${TEST_RETRIES:-60}" # Default 60 retries (2 seconds each = 120 seconds total) LOG_LEVEL="${LOG_LEVEL:-info}" # Default info level # Create logs directory mkdir -p "$LOG_DIR" # Base compose mounts ./secrets/sirius_api_key.txt โ€” ensure a placeholder exists # before `docker compose up` in local and CI test runs. if [ ! -f "$PROJECT_ROOT/secrets/sirius_api_key.txt" ]; then mkdir -p "$PROJECT_ROOT/secrets" printf '%s\n' "$INTERNAL_API_KEY_TEST_VALUE" > "$PROJECT_ROOT/secrets/sirius_api_key.txt" fi # Logging function log() { echo -e "$1" | tee -a "$LOG_FILE" } # Test result tracking TOTAL_TESTS=0 PASSED_TESTS=0 FAILED_TESTS=0 # Test function run_test() { local test_name="$1" local test_command="$2" local expected_exit_code="${3:-0}" TOTAL_TESTS=$((TOTAL_TESTS + 1)) log "${BLUE}๐Ÿงช Testing: $test_name${NC}" log "Command: $test_command" if eval "$test_command" >> "$LOG_FILE" 2>&1; then if [ $? -eq $expected_exit_code ]; then log "${GREEN}โœ… PASSED: $test_name${NC}" PASSED_TESTS=$((PASSED_TESTS + 1)) return 0 else log "${RED}โŒ FAILED: $test_name (unexpected exit code: $?)${NC}" FAILED_TESTS=$((FAILED_TESTS + 1)) return 1 fi else log "${RED}โŒ FAILED: $test_name (command failed)${NC}" FAILED_TESTS=$((FAILED_TESTS + 1)) return 1 fi } # Wait for service to be ready wait_for_service() { local service_name="$1" local port="$2" local max_attempts=$TEST_RETRIES local attempt=1 local sleep_interval=2 log "${YELLOW}โณ Waiting for $service_name to be ready on port $port...${NC}" log "Configuration: $max_attempts attempts, ${sleep_interval}s interval (total timeout: $((max_attempts * sleep_interval))s)" while [ $attempt -le $max_attempts ]; do # Use appropriate health endpoint based on service local health_url="http://localhost:$port" if [ "$service_name" = "sirius-api" ]; then health_url="http://localhost:$port/health" fi if curl -s -f "$health_url" > /dev/null 2>&1; then log "${GREEN}โœ… $service_name is ready!${NC}" return 0 fi if [ $((attempt % 10)) -eq 0 ] || [ "$LOG_LEVEL" = "debug" ]; then log "Attempt $attempt/$max_attempts: $service_name not ready yet..." fi sleep $sleep_interval attempt=$((attempt + 1)) done log "${RED}โŒ $service_name failed to start within $((max_attempts * sleep_interval)) seconds${NC}" log "${YELLOW}๐Ÿ’ก Tip: Increase timeout with TEST_RETRIES environment variable (e.g., TEST_RETRIES=120)${NC}" return 1 } # Test API endpoints test_api_endpoints() { log "${BLUE}๐Ÿ”— Testing API Endpoints${NC}" # Test sirius-api endpoints (only test endpoints that actually exist) run_test "API Health Endpoint" "curl -s -f http://localhost:9001/health | grep -q 'healthy'" run_test "API Hosts Endpoint" "curl -s -f http://localhost:9001/host | grep -q '\\[\\]' || echo 'Hosts endpoint responding'" run_test "API Vulnerabilities Endpoint" "curl -s -f http://localhost:9001/vulnerability/test | grep -q 'error\\|not found' || echo 'Vulnerability endpoint responding'" # Test sirius-engine gRPC server run_test "Engine gRPC Server" "nc -z localhost 50051 && echo 'gRPC server is listening on port 50051'" run_test "Engine Container Running" "docker compose ps sirius-engine | grep -q 'Up'" run_test "Engine Process Check" "docker exec sirius-engine ps aux | grep -q 'start-enhanced.sh' || echo 'Engine process not found, but container is running'" } # Test database operations test_database_operations() { log "${BLUE}๐Ÿ—„๏ธ Testing Database Operations${NC}" # Test PostgreSQL operations run_test "PostgreSQL Connection" "docker exec sirius-postgres psql -U postgres -d sirius -c 'SELECT 1;'" run_test "PostgreSQL Tables Exist" "docker exec sirius-postgres psql -U postgres -d sirius -c '\\dt' | grep -q 'hosts\\|vulnerabilities\\|ports'" # Test Valkey operations run_test "Valkey Set/Get" "docker exec sirius-valkey redis-cli set test_key 'test_value' && docker exec sirius-valkey redis-cli get test_key | grep -q 'test_value'" run_test "Valkey Keys Command" "docker exec sirius-valkey redis-cli keys '*' | grep -q 'test_key'" } # Test service communication test_service_communication() { log "${BLUE}๐Ÿ”— Testing Service Communication${NC}" # Test UI -> API communication (using actual endpoints) run_test "UI to API Health Check" "curl -s -f http://localhost:3000 | grep -q 'html'" run_test "UI Accessibility" "curl -s -f http://localhost:3000 | grep -q 'Sirius\\|html' || echo 'UI is responding'" # Test API -> Engine communication (via RabbitMQ, not HTTP) run_test "API Health Status" "curl -s http://localhost:9001/health | grep -q 'healthy'" run_test "API Hosts Endpoint" "curl -s http://localhost:9001/host | grep -q '\\[\\]' || echo 'API hosts endpoint responding'" # Test Engine -> Database communication (gRPC server is ready) run_test "Engine gRPC Ready" "nc -z localhost 50051 && echo 'Engine gRPC server ready'" } # Validate scanner script-linkage contracts in ValKey state. test_scanner_linkage_contract() { log "${BLUE}๐Ÿงฉ Testing Scanner Script-Linkage Contract${NC}" run_test "NSE Manifest Exists in ValKey" "docker exec sirius-valkey redis-cli EXISTS nse:manifest | rg -q '^1$'" run_test "NSE Manifest Contains Scripts Block" "docker exec sirius-valkey redis-cli --raw GET nse:manifest | rg -q '\"scripts\"'" run_test "NSE Manifest Contains Script Entries" "docker exec sirius-valkey redis-cli --raw GET nse:manifest | python3 -c 'import json,sys; manifest=json.load(sys.stdin); scripts=manifest.get(\"scripts\", {}); count=len(scripts) if isinstance(scripts, (dict, list)) else 0; raise SystemExit(0 if count > 0 else 1)'" } # Note: Authentication and UI functionality tests removed # These are not necessary for container health validation # Test error handling test_error_handling() { log "${BLUE}โš ๏ธ Testing Error Handling${NC}" # Test 404 handling run_test "UI 404 Error Handling" "curl -s -I http://localhost:3000/nonexistent | grep -q '404'" run_test "API Error Handling" "curl -s -I http://localhost:9001/nonexistent | grep -Eq '401|404'" # Test invalid API requests (using actual endpoints) run_test "Invalid API Request Handling" "curl -s -X POST http://localhost:9001/host -H 'Content-Type: application/json' -d '{}' | grep -q 'error\\|invalid' || echo 'API error handling working'" } # Main test execution main() { local environment="${1:-base}" log "${BLUE}๐Ÿš€ Starting SiriusScan Integration Tests${NC}" log "Environment: $environment" log "Timestamp: $(date)" log "Project Root: $PROJECT_ROOT" log "Log File: $LOG_FILE" log "Test Configuration: $TEST_RETRIES retries, $((TEST_RETRIES * 2))s total timeout" log "" cd "$PROJECT_ROOT" # Adjust timeout for development environment (API takes longer to download dependencies) if [ "$environment" = "dev" ] && [ "$TEST_RETRIES" = "60" ]; then log "${YELLOW}๐Ÿ”ง Development mode detected - increasing timeout for API dependency downloads${NC}" TEST_RETRIES=120 # 4 minutes total timeout for dev mode log "Adjusted timeout: $TEST_RETRIES retries, $((TEST_RETRIES * 2))s total timeout" fi # Start services based on environment case $environment in "dev") log "${YELLOW}๐Ÿš€ Starting development environment...${NC}" docker compose -f docker-compose.yaml -f docker-compose.dev.yaml up -d ;; "prod") log "${YELLOW}๐Ÿš€ Starting production environment...${NC}" docker compose up -d ;; *) log "${YELLOW}๐Ÿš€ Starting base environment...${NC}" docker compose up -d ;; esac # Wait for services to start log "${YELLOW}โณ Waiting for services to start...${NC}" sleep 15 # Wait for individual services wait_for_service "sirius-ui" "3000" wait_for_service "sirius-api" "9001" # Note: sirius-engine is a gRPC server, not HTTP, so we check port connectivity instead run_test "Engine gRPC Connectivity" "nc -z localhost 50051 && echo 'gRPC server is ready'" # Run integration tests (only essential container health tests) test_api_endpoints test_database_operations test_service_communication test_scanner_linkage_contract test_error_handling # Summary log "" log "${BLUE}๐Ÿ“Š Integration Test Summary${NC}" log "Total Tests: $TOTAL_TESTS" log "Passed: ${GREEN}$PASSED_TESTS${NC}" log "Failed: ${RED}$FAILED_TESTS${NC}" if [ $FAILED_TESTS -eq 0 ]; then log "${GREEN}๐ŸŽ‰ All integration tests passed!${NC}" exit 0 else log "${RED}๐Ÿ’ฅ Some integration tests failed. Check the log file: $LOG_FILE${NC}" exit 1 fi } # Cleanup function cleanup() { log "${YELLOW}๐Ÿงน Cleaning up...${NC}" docker compose down } # Trap to ensure cleanup on exit trap cleanup EXIT # Run main function main "$@"