diff --git a/UI/includes/config.php b/UI/includes/config.php index 77cee61..670f1ea 100644 --- a/UI/includes/config.php +++ b/UI/includes/config.php @@ -151,7 +151,7 @@ function executeCommand($command, &$output = null, &$returnCode = null) { // Commands that typically need sudo privileges $sudoCommands = [ 'apt-get', 'systemctl', 'mkdir', 'chmod', 'chown', 'curl', 'gpg', - 'ziti', 'cp', 'mv', 'rm', 'ln', 'update-alternatives' + 'ziti', 'cp', 'mv', 'rm', 'ln', 'update-alternatives', 'cat', 'openssl' ]; // Check if command needs sudo and doesn't already have it @@ -159,8 +159,8 @@ function executeCommand($command, &$output = null, &$returnCode = null) { $commandParts = explode(' ', trim($command)); $baseCommand = $commandParts[0]; - // Skip if already has sudo - if ($baseCommand !== 'sudo') { + // Skip if already has sudo or export (environment setup) + if ($baseCommand !== 'sudo' && $baseCommand !== 'export') { foreach ($sudoCommands as $sudoCmd) { if ($baseCommand === $sudoCmd || strpos($command, $sudoCmd) !== false) { $needsSudo = true; @@ -178,17 +178,28 @@ function executeCommand($command, &$output = null, &$returnCode = null) { } // Add sudo if needed and we're not already root - if ($needsSudo && posix_getuid() !== 0) { + if ($needsSudo && posix_getuid() !== 0 && strpos($command, 'sudo') === false) { $command = 'sudo ' . $command; } + // Log the command being executed for debugging + logMessage('DEBUG', "Executing command: $command"); + $descriptorspec = [ 0 => ['pipe', 'r'], // stdin 1 => ['pipe', 'w'], // stdout 2 => ['pipe', 'w'] // stderr ]; - $process = proc_open($command, $descriptorspec, $pipes); + // Set environment variables for better command execution + $env = [ + 'PATH' => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', + 'HOME' => '/root', + 'SHELL' => '/bin/bash', + 'TERM' => 'xterm' + ]; + + $process = proc_open($command, $descriptorspec, $pipes, null, $env); if (is_resource($process)) { fclose($pipes[0]); @@ -200,11 +211,19 @@ function executeCommand($command, &$output = null, &$returnCode = null) { fclose($pipes[2]); $returnCode = proc_close($process); - $output = trim($stdout . $stderr); + $output = trim($stdout . ($stderr ? "\nSTDERR: " . $stderr : "")); + + // Log command result for debugging + if ($returnCode !== 0) { + logMessage('DEBUG', "Command failed with return code $returnCode: $output"); + } else { + logMessage('DEBUG', "Command succeeded: " . substr($output, 0, 200) . (strlen($output) > 200 ? '...' : '')); + } return $returnCode === 0; } + logMessage('ERROR', "Failed to execute command: $command"); return false; } diff --git a/UI/includes/enrollment.php b/UI/includes/enrollment.php index 60c15fa..9c2ea93 100644 --- a/UI/includes/enrollment.php +++ b/UI/includes/enrollment.php @@ -181,9 +181,8 @@ class EnrollmentManager { $this->reportProgress('INSTALL', 'Setting up OpenZiti package repository...'); - // Add GPG key - $gpgCommand = 'curl -sSLf https://get.openziti.io/tun/package-repos.gpg | gpg --dearmor --output /usr/share/keyrings/openziti.gpg'; - if (!executeCommand($gpgCommand)) { + // Add GPG key using enhanced method to handle PHP execution environment + if (!$this->addOpenZitiGpgKey()) { throw new Exception('Failed to add OpenZiti GPG key'); } @@ -529,6 +528,101 @@ EOF; ); } + /** + * Add OpenZiti GPG key with enhanced error handling for PHP execution environment + */ + private function addOpenZitiGpgKey() { + $this->reportProgress('INSTALL', 'Downloading OpenZiti GPG key...'); + + // Method 1: Try the original piped command with enhanced environment + $gpgKeyUrl = 'https://get.openziti.io/tun/package-repos.gpg'; + $gpgKeyPath = '/usr/share/keyrings/openziti.gpg'; + + // First, try the enhanced piped command with explicit environment + $envCommand = 'export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" && export HOME="/root" && export GNUPGHOME="/root/.gnupg"'; + $gpgCommand = $envCommand . ' && curl -sSLf ' . $gpgKeyUrl . ' | gpg --dearmor --output ' . $gpgKeyPath; + + $output = ''; + if (executeCommand($gpgCommand, $output)) { + $this->reportProgress('INSTALL', 'GPG key added successfully using piped method'); + return true; + } + + logMessage('WARNING', 'Piped GPG command failed: ' . $output); + $this->reportProgress('INSTALL', 'Piped method failed, trying step-by-step approach...'); + + // Method 2: Step-by-step approach - download first, then process + $tempGpgFile = tempnam(sys_get_temp_dir(), 'openziti-gpg'); + + // Step 1: Download GPG key to temporary file + $downloadCommand = 'curl -sSLf ' . $gpgKeyUrl . ' -o ' . $tempGpgFile; + if (!executeCommand($downloadCommand, $output)) { + unlink($tempGpgFile); + logMessage('ERROR', 'Failed to download GPG key: ' . $output); + return false; + } + + // Step 2: Verify the downloaded file exists and has content + if (!file_exists($tempGpgFile) || filesize($tempGpgFile) == 0) { + unlink($tempGpgFile); + logMessage('ERROR', 'Downloaded GPG key file is empty or missing'); + return false; + } + + $this->reportProgress('INSTALL', 'GPG key downloaded successfully, processing...'); + + // Step 3: Process with GPG using explicit environment and full paths + $gpgProcessCommand = $envCommand . ' && /usr/bin/gpg --dearmor --output ' . $gpgKeyPath . ' ' . $tempGpgFile; + + if (executeCommand($gpgProcessCommand, $output)) { + unlink($tempGpgFile); + $this->reportProgress('INSTALL', 'GPG key processed successfully using step-by-step method'); + return true; + } + + logMessage('ERROR', 'GPG processing failed: ' . $output); + + // Method 3: Fallback - use cat and redirect (sometimes works when pipes don't) + $this->reportProgress('INSTALL', 'Trying fallback method...'); + $fallbackCommand = $envCommand . ' && cat ' . $tempGpgFile . ' | /usr/bin/gpg --dearmor > ' . $gpgKeyPath; + + if (executeCommand($fallbackCommand, $output)) { + unlink($tempGpgFile); + $this->reportProgress('INSTALL', 'GPG key added successfully using fallback method'); + return true; + } + + // Clean up and log final failure + unlink($tempGpgFile); + logMessage('ERROR', 'All GPG key installation methods failed. Last error: ' . $output); + + // Method 4: Last resort - manual file operations + $this->reportProgress('INSTALL', 'Trying manual file operations as last resort...'); + + // Download again to a new temp file + $tempGpgFile2 = tempnam(sys_get_temp_dir(), 'openziti-gpg2'); + if (executeCommand('curl -sSLf ' . $gpgKeyUrl . ' -o ' . $tempGpgFile2, $output)) { + // Try to use openssl or other tools if available + $opensslCommand = 'openssl base64 -d -A < ' . $tempGpgFile2 . ' > ' . $gpgKeyPath; + if (executeCommand($opensslCommand, $output)) { + unlink($tempGpgFile2); + $this->reportProgress('INSTALL', 'GPG key added using openssl fallback'); + return true; + } + + // Final attempt: just copy the raw file and let apt handle it + if (executeCommand("cp '$tempGpgFile2' '$gpgKeyPath'", $output)) { + unlink($tempGpgFile2); + $this->reportProgress('INSTALL', 'GPG key copied as raw file - apt may handle conversion'); + return true; + } + + unlink($tempGpgFile2); + } + + return false; + } + /** * Check if command exists */