#!/bin/bash # ============================================================================== # WALLARM PREFLIGHT CHECK SCRIPT - V1.3 (Docker deployment) # ============================================================================== # Purpose: Validate system readiness for Wallarm Docker deployment # Features: # - Non-interactive system validation (sudo, OS, architecture, init system) # - Network connectivity testing (US/EU cloud) # - Docker artifact source validation (Git Repositorys / local binaries/images) # - Outputs results to .env file for deployment script # - DAU-friendly error messages with remediation # ============================================================================== # Script location and shared library (colors, logging, validation, detection, connectivity) SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # shellcheck source=./wallarm-lib.sh source "$SCRIPT_DIR/wallarm-lib.sh" # Strict error handling set -euo pipefail trap early_error_handler ERR # Configuration ENV_FILE=".env" LOG_FILE="${HOME:-.}/logs/wallarm-check.log" # Git Repositorys artifact URLs (primary source) - Docker deployment artifacts GIT_BASE_URL="https://git.sechpoint.app/customer-engineering/wallarm" GIT_RAW_URL="https://git.sechpoint.app/customer-engineering/wallarm/raw/branch/main" GIT_DOCKER_BINARY_URL="${GIT_RAW_URL}/docker/binaries/docker-29.2.1.tgz" GIT_WALLARM_IMAGE_URL="${GIT_RAW_URL}/docker/images/wallarm-node-6.11.0-rc1.tar.gz" # Local artifact directories (relative to script location) LOCAL_BINARY_DIR="${SCRIPT_DIR}/binaries" LOCAL_IMAGE_DIR="${SCRIPT_DIR}/images" # Cloud endpoints (from Wallarm documentation) EU_DATA_NODES=("api.wallarm.com" "node-data0.eu1.wallarm.com" "node-data1.eu1.wallarm.com") US_DATA_NODES=("us1.api.wallarm.com" "node-data0.us1.wallarm.com" "node-data1.us1.wallarm.com") # Global result tracking CHECK_RESULT="pass" CHECK_ERRORS=() GIT_REACHABLE="false" # ============================================================================== # RESULT TRACKING & ENV FILE # ============================================================================== add_error() { local error_msg="$1" CHECK_ERRORS+=("$error_msg") CHECK_RESULT="fail" log_message "ERROR" "$error_msg" } write_env_file() { local os_name="$1" local os_version="$2" local architecture="$3" local init_system="$4" local us_cloud_reachable="$5" local eu_cloud_reachable="$6" local registry_reachable="$7" local download_reachable="$8" local git_reachable="${9:-false}" cat > "$ENV_FILE" << EOF # Wallarm Preflight Check Results # Generated: $(date '+%Y-%m-%d %H:%M:%S') # Script: $0 result=$CHECK_RESULT os_name=$os_name os_version=$os_version architecture=$architecture init_system=$init_system us_cloud_reachable=$us_cloud_reachable eu_cloud_reachable=$eu_cloud_reachable registry_reachable=$registry_reachable download_reachable=$download_reachable git_reachable=$git_reachable EOF if [ ${#CHECK_ERRORS[@]} -gt 0 ]; then echo "# Errors:" >> "$ENV_FILE" for i in "${!CHECK_ERRORS[@]}"; do echo "error_$i=\"${CHECK_ERRORS[$i]}\"" >> "$ENV_FILE" done fi log_message "SUCCESS" "Check results written to $ENV_FILE" } # ============================================================================== # PRE-FLIGHT VALIDATION FUNCTIONS # ============================================================================== validate_sudo_access() { log_message "INFO" "Validating sudo access..." local os_name os_name=$(uname -s | tr '[:upper:]' '[:lower:]') if ! command -v sudo >/dev/null 2>&1; then add_error "sudo command not found" return 1 fi if [ "$os_name" = "darwin" ]; then log_message "WARNING" "macOS detected: sudo authentication test skipped (may prompt during deployment)" log_message "INFO" "Note: macOS is not a supported deployment target. This check is for Linux servers." return 0 fi if ! sudo -v; then add_error "sudo authentication failed" return 1 fi log_message "SUCCESS" "Sudo access validated" return 0 } validate_required_commands() { log_message "INFO" "Validating required system commands..." local missing_commands=() local os_name os_name=$(uname -s | tr '[:upper:]' '[:lower:]') # Core commands required for both check and deployment scripts local core_commands=( "tar" # Required for extracting Docker binaries in deployment "curl" # Required for connectivity testing "grep" # Used extensively "cut" # Used for parsing output "tr" # Used for text transformations "sed" # Used for text processing "head" # Used for limiting output "tail" # Used for limiting output "ls" # Used for file listing "date" # Used for logging timestamps "mkdir" # Used for creating directories "chmod" # Used for permission changes "stat" # Used for file information (required for file size checks) "tee" # Required for writing configuration files "cp" # Required for copying Docker binaries "rm" # Required for cleanup operations ) # Linux-specific commands (not available on macOS) if [ "$os_name" != "darwin" ]; then core_commands+=( "getent" # Required for checking group existence "groupadd" # Required for creating docker group (sudo) "usermod" # Required for adding user to docker group (sudo) "iptables" # Required for Docker network bridge creation (Docker static binaries v1.4+) ) fi # Check each core command (command_exists comes from common library) local cmd for cmd in "${core_commands[@]}"; do if ! command_exists "$cmd"; then missing_commands+=("$cmd") fi done # Check for port checking utility (ss or netstat) if [ "$os_name" != "darwin" ]; then if ! command_exists ss && ! command_exists netstat; then missing_commands+=("ss or netstat") fi fi # Detect init system and validate its control command if [ "$os_name" != "darwin" ]; then local init_system init_system=$(detect_init_system) case "$init_system" in "systemd") if ! command_exists systemctl; then missing_commands+=("systemctl") fi ;; "openrc") if ! command_exists rc-service; then missing_commands+=("rc-service") fi ;; "sysvinit") if ! command_exists service; then missing_commands+=("service") fi ;; "upstart") if ! command_exists initctl; then missing_commands+=("initctl") fi ;; *) log_message "WARNING" "Unknown init system '$init_system', cannot validate init command" ;; esac else log_message "INFO" "Skipping init system validation on macOS (not a deployment target)" fi if [ ${#missing_commands[@]} -gt 0 ]; then local missing_list missing_list=$(IFS=', '; echo "${missing_commands[*]}") add_error "Missing required commands: $missing_list" log_message "ERROR" "Please install missing commands and run the check again." return 1 fi # Special check: iptables version must be 1.4 or higher for Docker static binaries if [ "$os_name" != "darwin" ]; then log_message "INFO" "Checking iptables version (requires 1.4+ for Docker)..." if command_exists iptables; then local iptables_version iptables_version=$(iptables --version 2>/dev/null | head -1 | grep -o '[0-9]\+\.[0-9]\+' | head -1) if [ -n "$iptables_version" ]; then log_message "INFO" "Found iptables version $iptables_version" local major_version minor_version major_version=$(echo "$iptables_version" | cut -d. -f1) minor_version=$(echo "$iptables_version" | cut -d. -f2) if [ "$major_version" -lt 1 ] || ([ "$major_version" -eq 1 ] && [ "$minor_version" -lt 4 ]); then add_error "iptables version $iptables_version is too old. Docker requires iptables 1.4 or higher." log_message "ERROR" "Please upgrade iptables to version 1.4 or higher." return 1 fi else log_message "WARNING" "Could not determine iptables version, continuing anyway" fi else add_error "iptables command not found (required for Docker network bridge)" return 1 fi else log_message "INFO" "Skipping iptables check on macOS (not a deployment target)" fi log_message "SUCCESS" "All required system commands are available" return 0 } # ============================================================================== # NETWORK CONNECTIVITY & ARTIFACT SOURCE TESTING # ============================================================================== perform_network_tests() { log_message "INFO" "=== NETWORK CONNECTIVITY TESTING ===" # Test US cloud endpoints local us_reachable us_reachable=$(test_cloud_endpoints "US" "${US_DATA_NODES[@]}") # Test EU cloud endpoints local eu_reachable eu_reachable=$(test_cloud_endpoints "EU" "${EU_DATA_NODES[@]}") local registry_reachable="false" local download_reachable="false" # Check for local fallback resources (multiple locations) log_message "INFO" "Checking for local artifact fallback resources..." # Docker binary locations (priority: local binaries directory -> current directory) local has_local_docker=false local docker_sources=() if [ -d "$LOCAL_BINARY_DIR" ]; then log_message "INFO" "Checking local binaries directory: $LOCAL_BINARY_DIR" local binary_files binary_files=$(ls "$LOCAL_BINARY_DIR"/*.tgz 2>/dev/null | head -5) if [ -n "$binary_files" ]; then log_message "SUCCESS" "Found local Docker binaries in $LOCAL_BINARY_DIR:" while IFS= read -r file; do log_message "SUCCESS" " - $(basename "$file")" done <<< "$binary_files" has_local_docker=true docker_sources+=("$LOCAL_BINARY_DIR/") fi fi local current_docker_files current_docker_files=$(ls docker-*.tgz 2>/dev/null | head -5) if [ -n "$current_docker_files" ]; then log_message "SUCCESS" "Found local Docker binaries in current directory:" while IFS= read -r file; do log_message "SUCCESS" " - $file" done <<< "$current_docker_files" has_local_docker=true docker_sources+=("current directory") fi if [ "$has_local_docker" = "false" ]; then log_message "WARNING" "No local Docker binaries found in $LOCAL_BINARY_DIR/ or current directory" else log_message "INFO" "Docker binary sources: ${docker_sources[*]}" fi # Wallarm image locations (priority: local images directory -> current directory) local has_local_wallarm=false local wallarm_sources=() if [ -d "$LOCAL_IMAGE_DIR" ]; then log_message "INFO" "Checking local images directory: $LOCAL_IMAGE_DIR" local image_files image_files=$(ls "$LOCAL_IMAGE_DIR"/*.tar.gz "$LOCAL_IMAGE_DIR"/*.tar 2>/dev/null | head -5) if [ -n "$image_files" ]; then log_message "SUCCESS" "Found local Wallarm images in $LOCAL_IMAGE_DIR:" while IFS= read -r file; do log_message "SUCCESS" " - $(basename "$file")" done <<< "$image_files" has_local_wallarm=true wallarm_sources+=("$LOCAL_IMAGE_DIR/") fi fi local current_image_files current_image_files=$(ls wallarm-node-*.tar.gz wallarm-node-*.tar 2>/dev/null | head -5) if [ -n "$current_image_files" ]; then log_message "SUCCESS" "Found local Wallarm images in current directory:" while IFS= read -r file; do log_message "SUCCESS" " - $file" done <<< "$current_image_files" has_local_wallarm=true wallarm_sources+=("current directory") fi if [ "$has_local_wallarm" = "false" ]; then log_message "WARNING" "No local Wallarm images found in $LOCAL_IMAGE_DIR/ or current directory" else log_message "INFO" "Wallarm image sources: ${wallarm_sources[*]}" fi echo "$us_reachable:$eu_reachable:$registry_reachable:$download_reachable" } # ============================================================================== # MAIN FUNCTION # ============================================================================== main() { clear echo -e "${BLUE}${BOLD}" echo "╔══════════════════════════════════════════════════════════════╗" echo "║ WALLARM PREFLIGHT CHECK SCRIPT (Docker) - V1.3 ║" echo "║ System Readiness Validation for Deployment ║" echo "╚══════════════════════════════════════════════════════════════╝${NC}" echo -e "\n${YELLOW}Starting preflight check at: $(date)${NC}" # Initialize logging local log_dir="${HOME:-.}/logs" if [ ! -d "$log_dir" ]; then if ! mkdir -p "$log_dir"; then echo -e "${YELLOW}Cannot create log directory $log_dir, falling back to current directory...${NC}" log_dir="." fi fi LOG_FILE="$log_dir/wallarm-check.log" if ! : > "$LOG_FILE"; then echo -e "${RED}Cannot create log file at $LOG_FILE${NC}" echo -e "${YELLOW}Falling back to current directory...${NC}" LOG_FILE="./wallarm-check.log" : > "$LOG_FILE" 2>/dev/null || true fi if ! chmod 644 "$LOG_FILE" 2>/dev/null; then echo -e "${YELLOW}Warning: Could not set permissions on log file${NC}" fi log_message "INFO" "=== Wallarm Preflight Check Started ===" if [ "$INSECURE_SSL" = "1" ]; then log_message "WARNING" "SSL certificate validation is DISABLED (insecure). Set WALLARM_INSECURE_SSL=0 to enable validation." fi # Phase 1: System validation log_message "INFO" "=== PHASE 1: SYSTEM VALIDATION ===" if ! validate_required_commands; then add_error "Required system commands validation failed" fi if ! validate_sudo_access; then add_error "Sudo access validation failed" fi local os_info os_info=$(detect_os_and_version) local os_name os_name=$(echo "$os_info" | cut -d: -f1) local os_version os_version=$(echo "$os_info" | cut -d: -f2) local architecture architecture=$(detect_architecture) if [ "$architecture" = "unknown" ]; then add_error "Unsupported architecture detected" fi local init_system init_system=$(detect_init_system) log_message "SUCCESS" "System validation completed:" log_message "SUCCESS" " OS: $os_name $os_version" log_message "SUCCESS" " Architecture: $architecture" log_message "SUCCESS" " Init System: $init_system" # Phase 2: Network connectivity testing log_message "INFO" "=== PHASE 2: NETWORK CONNECTIVITY TESTING ===" log_message "INFO" "Testing connectivity to Git Repositorys artifact repository..." GIT_REACHABLE="false" if test_connectivity "$GIT_DOCKER_BINARY_URL" "Git Repositorys Docker artifact"; then GIT_REACHABLE="true" log_message "SUCCESS" "Git Repositorys Docker artifact is reachable (primary source)" else log_message "WARNING" "Git Repositorys Docker artifact is not reachable - will use fallback sources" fi local network_results network_results=$(perform_network_tests) local us_reachable us_reachable=$(echo "$network_results" | cut -d: -f1) local eu_reachable eu_reachable=$(echo "$network_results" | cut -d: -f2) local registry_reachable registry_reachable=$(echo "$network_results" | cut -d: -f3) local download_reachable download_reachable=$(echo "$network_results" | cut -d: -f4) # Critical check: Need at least one source for Docker and Wallarm # Priority: Git Repositorys (primary) -> local files if [ "$GIT_REACHABLE" = "true" ]; then log_message "SUCCESS" "Git Repositorys artifact repository is reachable (primary source available)" else log_message "WARNING" "Git Repositorys artifact repository is not reachable - checking fallback sources" local has_local_docker=false local has_local_wallarm=false if [ -d "$LOCAL_BINARY_DIR" ] && [ -n "$(ls "$LOCAL_BINARY_DIR"/*.tgz 2>/dev/null)" ]; then has_local_docker=true log_message "INFO" "Found local Docker binaries in $LOCAL_BINARY_DIR/" elif [ -n "$(ls docker-*.tgz 2>/dev/null)" ]; then has_local_docker=true log_message "INFO" "Found local Docker binaries in current directory" fi if [ -d "$LOCAL_IMAGE_DIR" ] && [ -n "$(ls "$LOCAL_IMAGE_DIR"/*.tar.gz "$LOCAL_IMAGE_DIR"/*.tar 2>/dev/null)" ]; then has_local_wallarm=true log_message "INFO" "Found local Wallarm images in $LOCAL_IMAGE_DIR/" elif [ -n "$(ls wallarm-node-*.tar.gz wallarm-node-*.tar 2>/dev/null)" ]; then has_local_wallarm=true log_message "INFO" "Found local Wallarm images in current directory" fi local has_sufficient_resources=true if [ "$has_local_docker" = "false" ]; then log_message "ERROR" "No Docker binary source available" log_message "ERROR" " - Git Repositorys artifacts unreachable: $GIT_RAW_URL" log_message "ERROR" " - Local binaries not found in $LOCAL_BINARY_DIR/ or current directory" has_sufficient_resources=false fi if [ "$has_local_wallarm" = "false" ]; then log_message "ERROR" "No Wallarm image source available" log_message "ERROR" " - Git Repositorys artifacts unreachable: $GIT_RAW_URL" log_message "ERROR" " - Local images not found in $LOCAL_IMAGE_DIR/ or current directory" has_sufficient_resources=false fi if [ "$has_sufficient_resources" = "false" ]; then add_error "Insufficient resources: Need at least one source for Docker and Wallarm artifacts. Possible sources: 1. Git Repositorys (primary): Ensure network access to $GIT_RAW_URL 2. Local files: Place artifacts in: - Docker binary: $LOCAL_BINARY_DIR/docker-29.2.1.tgz or current directory - Wallarm image: $LOCAL_IMAGE_DIR/wallarm-node-6.11.0-rc1.tar.gz or current directory" fi fi log_message "SUCCESS" "Network testing completed:" log_message "SUCCESS" " Git Repositorys Artifacts Reachable: $GIT_REACHABLE" log_message "SUCCESS" " US Cloud Reachable: $us_reachable" log_message "SUCCESS" " EU Cloud Reachable: $eu_reachable" log_message "SUCCESS" " Fallback Registry Reachable: $registry_reachable" log_message "SUCCESS" " Fallback Download Reachable: $download_reachable" # Phase 3: Write results log_message "INFO" "=== PHASE 3: WRITING RESULTS ===" write_env_file "$os_name" "$os_version" "$architecture" "$init_system" \ "$us_reachable" "$eu_reachable" "$registry_reachable" "$download_reachable" \ "$GIT_REACHABLE" # Final summary if [ "$CHECK_RESULT" = "pass" ]; then log_message "SUCCESS" "=== PREFLIGHT CHECK PASSED ===" echo -e "\n${GREEN}${BOLD}╔══════════════════════════════════════════════════════════════╗${NC}" echo -e "${GREEN}${BOLD}║ PREFLIGHT CHECK PASSED - SYSTEM READY ║${NC}" echo -e "${GREEN}${BOLD}╚══════════════════════════════════════════════════════════════╝${NC}" echo -e "\n${CYAN}System is ready for Wallarm Docker deployment.${NC}" echo -e "${YELLOW}Check results: $ENV_FILE${NC}" echo -e "${YELLOW}Full log: $LOG_FILE${NC}" echo -e "\n${GREEN}Next step: Run ./docker/wallarm-ct-deploy.sh to proceed with deployment${NC}" exit 0 else log_message "ERROR" "=== PREFLIGHT CHECK FAILED ===" echo -e "\n${RED}${BOLD}╔══════════════════════════════════════════════════════════════╗${NC}" echo -e "${RED}${BOLD}║ PREFLIGHT CHECK FAILED - SYSTEM NOT READY ║${NC}" echo -e "${RED}${BOLD}╚══════════════════════════════════════════════════════════════╝${NC}" echo -e "\n${YELLOW}${BOLD}Issues found:${NC}" for error in "${CHECK_ERRORS[@]}"; do echo -e " ${RED}•${NC} $error" done echo -e "\n${YELLOW}Check results: $ENV_FILE${NC}" echo -e "${YELLOW}Full log: $LOG_FILE${NC}" echo -e "\n${CYAN}Please fix the issues above and run the check again.${NC}" exit 1 fi } # ============================================================================== # SCRIPT EXECUTION # ============================================================================== # Ensure we're in bash if [ -z "$BASH_VERSION" ]; then echo "Error: This script must be run with bash" >&2 exit 1 fi # Run main function main "$@"