&1', $outputLines, $returnCode); $output = implode("\n", $outputLines); $duration = round((microtime(true) - $startTime) * 1000, 2); return [ 'command' => $command, 'description' => $description, 'success' => $returnCode === 0, 'returnCode' => $returnCode, 'output' => $output, 'duration' => $duration . 'ms' ]; } /** * Check file/directory status */ function checkPath($path, $description, $expectedType = 'file') { $exists = false; $readable = false; $writable = false; $size = 0; $permissions = ''; if (file_exists($path)) { $exists = true; $readable = is_readable($path); $writable = is_writable($path); if ($expectedType === 'file' && is_file($path)) { $size = filesize($path); } $permissions = substr(sprintf('%o', fileperms($path)), -4); } return [ 'path' => $path, 'description' => $description, 'exists' => $exists, 'readable' => $readable, 'writable' => $writable, 'size' => $size, 'permissions' => $permissions, 'type' => $expectedType ]; } /** * Run all pre-enrollment checks */ function runPreEnrollmentChecks() { $results = [ 'timestamp' => date('Y-m-d H:i:s T'), 'environment' => [], 'commands' => [], 'permissions' => [], 'network' => [], 'files' => [], 'recommendations' => [] ]; // Environment checks $results['environment'] = [ 'php_version' => PHP_VERSION, 'php_sapi' => php_sapi_name(), 'os' => PHP_OS, 'user' => get_current_user(), 'uid' => function_exists('posix_getuid') ? posix_getuid() : 'unknown', 'gid' => function_exists('posix_getgid') ? posix_getgid() : 'unknown', 'working_dir' => getcwd(), 'temp_dir' => sys_get_temp_dir() ]; // Command availability checks $commands = [ 'curl' => 'curl --version', 'gpg' => 'gpg --version', 'sudo' => 'sudo --version', 'systemctl' => 'systemctl --version', 'python3' => 'python3 --version', 'which' => 'which which', 'apt-get' => 'apt-get --version', 'jq' => 'jq --version' ]; foreach ($commands as $name => $command) { $results['commands'][$name] = checkCommand("which $name", "Check if $name is available"); if ($results['commands'][$name]['success']) { $results['commands'][$name . '_version'] = checkCommand($command, "Get $name version"); } } // Sudo permissions check $results['permissions']['sudo_test'] = checkCommand('sudo -n whoami', 'Test sudo access without password'); $results['permissions']['sudo_list'] = checkCommand('sudo -l', 'List sudo permissions'); // Network connectivity checks $results['network']['dns_resolution'] = checkCommand('nslookup get.openziti.io', 'DNS resolution for OpenZiti'); $results['network']['ping_test'] = checkCommand('ping -c 1 get.openziti.io', 'Ping OpenZiti server'); $results['network']['https_test'] = checkCommand('curl -I --connect-timeout 10 https://get.openziti.io', 'HTTPS connectivity test'); $results['network']['gpg_key_download'] = checkCommand('curl -I --connect-timeout 10 https://get.openziti.io/tun/package-repos.gpg', 'GPG key URL accessibility'); // File system checks $paths = [ '/usr/share/keyrings' => 'OpenZiti keyrings directory', '/usr/share/keyrings/openziti.gpg' => 'OpenZiti GPG key file', '/etc/apt/sources.list.d' => 'APT sources directory', '/etc/apt/sources.list.d/openziti-release.list' => 'OpenZiti repository file', '/tmp' => 'Temporary directory', '/var/log' => 'Log directory' ]; foreach ($paths as $path => $description) { $expectedType = (substr($path, -1) === '/' || is_dir($path)) ? 'directory' : 'file'; $results['files'][$path] = checkPath($path, $description, $expectedType); } // Generate recommendations $results['recommendations'] = generateRecommendations($results); return $results; } /** * Generate recommendations based on check results */ function generateRecommendations($results) { $recommendations = []; // Check if running as www-data if ($results['environment']['user'] === 'www-data') { $recommendations[] = [ 'type' => 'info', 'message' => 'Running as www-data user (web server context)', 'action' => 'This is expected for web-based enrollment' ]; } // Check sudo access if (!$results['permissions']['sudo_test']['success']) { $recommendations[] = [ 'type' => 'error', 'message' => 'Sudo access not working', 'action' => 'Run: sudo ./fix-permissions.sh or ensure www-data has proper sudo permissions' ]; } // Check required commands $requiredCommands = ['curl', 'gpg', 'sudo', 'systemctl']; foreach ($requiredCommands as $cmd) { if (!$results['commands'][$cmd]['success']) { $recommendations[] = [ 'type' => 'error', 'message' => "Required command '$cmd' not found", 'action' => "Install $cmd: sudo apt-get update && sudo apt-get install -y $cmd" ]; } } // Check network connectivity if (!$results['network']['https_test']['success']) { $recommendations[] = [ 'type' => 'error', 'message' => 'HTTPS connectivity to OpenZiti failed', 'action' => 'Check firewall settings and internet connectivity' ]; } // Check if GPG key already exists if ($results['files']['/usr/share/keyrings/openziti.gpg']['exists']) { $size = $results['files']['/usr/share/keyrings/openziti.gpg']['size']; if ($size > 0) { $recommendations[] = [ 'type' => 'success', 'message' => "OpenZiti GPG key already exists ($size bytes)", 'action' => 'GPG key installation should be skipped automatically' ]; } else { $recommendations[] = [ 'type' => 'warning', 'message' => 'OpenZiti GPG key file exists but is empty', 'action' => 'Remove the empty file: sudo rm /usr/share/keyrings/openziti.gpg' ]; } } // Check keyrings directory if (!$results['files']['/usr/share/keyrings']['exists']) { $recommendations[] = [ 'type' => 'warning', 'message' => 'Keyrings directory does not exist', 'action' => 'Will be created automatically during enrollment' ]; } return $recommendations; } /** * Output results in HTML format */ function outputHTML($results) { ?>
Purpose: Verify system readiness for ZitiNexus Router enrollment
Time:
| Command | Status | Details |
|---|---|---|
| Path | Status | Size | Permissions | Description |
|---|---|---|---|---|
| 0 ? number_format($info['size']) . ' bytes' : '-'; ?> |
sudo ./fix-permissions.sh/var/www/ziti-enrollment/logs/ if enrollment fails