fixed script new2

This commit is contained in:
Edmund Tan 2025-07-22 22:14:33 +08:00
parent 360249f22e
commit 8e225fdedd
1 changed files with 357 additions and 0 deletions

View File

@ -0,0 +1,357 @@
<?php
/**
* Command Execution Diagnostic Script
* Tests various aspects of command execution, permissions, and environment
* to identify issues with GPG key installation on CloudStack instances
*/
// Include config for logging functions
require_once 'includes/config.php';
// Start output buffering for clean HTML output
ob_start();
// Set content type
header('Content-Type: text/html; charset=UTF-8');
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Command Execution Diagnostics</title>
<style>
body { font-family: monospace; margin: 20px; background: #f5f5f5; }
.container { max-width: 1200px; margin: 0 auto; background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }
.test-section { margin: 20px 0; padding: 15px; border: 1px solid #ddd; border-radius: 5px; }
.test-section h3 { margin-top: 0; color: #333; border-bottom: 2px solid #007bff; padding-bottom: 5px; }
.success { background-color: #d4edda; border-color: #c3e6cb; color: #155724; }
.warning { background-color: #fff3cd; border-color: #ffeaa7; color: #856404; }
.error { background-color: #f8d7da; border-color: #f5c6cb; color: #721c24; }
.info { background-color: #d1ecf1; border-color: #bee5eb; color: #0c5460; }
.command { background: #f8f9fa; padding: 10px; border-left: 4px solid #007bff; margin: 10px 0; font-family: 'Courier New', monospace; }
.output { background: #2d3748; color: #e2e8f0; padding: 10px; border-radius: 4px; margin: 10px 0; white-space: pre-wrap; font-family: 'Courier New', monospace; }
.summary { background: #e3f2fd; padding: 15px; border-radius: 5px; margin: 20px 0; }
table { width: 100%; border-collapse: collapse; margin: 10px 0; }
th, td { padding: 8px; text-align: left; border-bottom: 1px solid #ddd; }
th { background-color: #f2f2f2; }
.btn { display: inline-block; padding: 10px 20px; background: #007bff; color: white; text-decoration: none; border-radius: 4px; margin: 5px; }
.btn:hover { background: #0056b3; }
</style>
</head>
<body>
<div class="container">
<h1>🔍 Command Execution Diagnostics</h1>
<p><strong>Purpose:</strong> Diagnose why GPG key installation fails on CloudStack instance</p>
<p><strong>Time:</strong> <?php echo date('Y-m-d H:i:s T'); ?></p>
<?php
// Initialize results array
$results = [];
$issues = [];
$recommendations = [];
/**
* Helper function to execute command and capture detailed output
*/
function testCommand($description, $command, $expectSuccess = true) {
global $results, $issues;
echo "<div class='test-section'>";
echo "<h3>$description</h3>";
echo "<div class='command'>Command: $command</div>";
$startTime = microtime(true);
// Test using our executeCommand function
$output = '';
$returnCode = null;
$success = executeCommand($command, $output, $returnCode);
$endTime = microtime(true);
$duration = round(($endTime - $startTime) * 1000, 2);
$result = [
'description' => $description,
'command' => $command,
'success' => $success,
'return_code' => $returnCode,
'output' => $output,
'duration_ms' => $duration,
'expected_success' => $expectSuccess
];
$results[] = $result;
// Display result
$statusClass = $success ? 'success' : 'error';
if ($success && !$expectSuccess) $statusClass = 'warning';
if (!$success && !$expectSuccess) $statusClass = 'info';
echo "<div class='$statusClass'>";
echo "<strong>Status:</strong> " . ($success ? "✅ SUCCESS" : "❌ FAILED") . "<br>";
echo "<strong>Return Code:</strong> $returnCode<br>";
echo "<strong>Duration:</strong> {$duration}ms<br>";
echo "</div>";
if ($output) {
echo "<div class='output'>$output</div>";
}
// Track issues
if ($expectSuccess && !$success) {
$issues[] = "$description failed: $output";
}
echo "</div>";
return $result;
}
/**
* Test PHP environment information
*/
echo "<div class='test-section info'>";
echo "<h3>📋 PHP Environment Information</h3>";
echo "<table>";
echo "<tr><th>Property</th><th>Value</th></tr>";
echo "<tr><td>PHP Version</td><td>" . PHP_VERSION . "</td></tr>";
echo "<tr><td>PHP SAPI</td><td>" . php_sapi_name() . "</td></tr>";
echo "<tr><td>Operating System</td><td>" . PHP_OS . "</td></tr>";
echo "<tr><td>Current User (PHP)</td><td>" . get_current_user() . "</td></tr>";
echo "<tr><td>Process UID</td><td>" . (function_exists('posix_getuid') ? posix_getuid() : 'N/A') . "</td></tr>";
echo "<tr><td>Process GID</td><td>" . (function_exists('posix_getgid') ? posix_getgid() : 'N/A') . "</td></tr>";
echo "<tr><td>Process PID</td><td>" . getmypid() . "</td></tr>";
echo "<tr><td>Memory Limit</td><td>" . ini_get('memory_limit') . "</td></tr>";
echo "<tr><td>Max Execution Time</td><td>" . ini_get('max_execution_time') . "s</td></tr>";
echo "<tr><td>Disable Functions</td><td>" . (ini_get('disable_functions') ?: 'None') . "</td></tr>";
echo "</table>";
echo "</div>";
/**
* Test environment variables
*/
echo "<div class='test-section info'>";
echo "<h3>🌍 Environment Variables</h3>";
$envVars = ['PATH', 'HOME', 'USER', 'SHELL', 'TERM', 'PWD', 'SUDO_USER', 'SUDO_UID', 'SUDO_GID'];
echo "<table>";
echo "<tr><th>Variable</th><th>Value</th></tr>";
foreach ($envVars as $var) {
$value = getenv($var) ?: $_SERVER[$var] ?? 'Not Set';
echo "<tr><td>$var</td><td>$value</td></tr>";
}
echo "</table>";
echo "</div>";
/**
* Test basic command execution
*/
echo "<h2>🔧 Basic Command Tests</h2>";
testCommand("Current Working Directory", "pwd");
testCommand("Current User Identity", "whoami");
testCommand("Detailed User Info", "id");
testCommand("Hostname", "hostname");
testCommand("Date/Time", "date");
/**
* Test sudo access
*/
echo "<h2>🔐 Sudo Access Tests</h2>";
testCommand("Sudo Version", "sudo --version");
testCommand("Sudo Non-Interactive Test", "sudo -n whoami");
testCommand("Sudo List Permissions", "sudo -l", false); // May fail, that's ok
testCommand("Test Sudo Echo", "sudo echo 'sudo test successful'");
/**
* Test network connectivity
*/
echo "<h2>🌐 Network Connectivity Tests</h2>";
testCommand("Curl Version", "curl --version");
testCommand("Test DNS Resolution", "nslookup get.openziti.io", false);
testCommand("Test Ping to OpenZiti", "ping -c 1 get.openziti.io", false);
testCommand("Test HTTPS Connection", "curl -I https://get.openziti.io", false);
testCommand("Test GPG Key URL", "curl -sSLf https://get.openziti.io/tun/package-repos.gpg -o /dev/null");
/**
* Test GPG functionality
*/
echo "<h2>🔑 GPG Functionality Tests</h2>";
testCommand("GPG Version", "gpg --version");
testCommand("Which GPG", "which gpg");
testCommand("GPG List Keys", "gpg --list-keys", false);
testCommand("Test GPG Dearmor", "echo 'test' | gpg --dearmor", false);
/**
* Test file system permissions
*/
echo "<h2>📁 File System Permission Tests</h2>";
testCommand("Test /tmp Write", "touch /tmp/test-write-" . uniqid() . " && echo 'Write test successful'");
testCommand("Test /usr/share Access", "ls -la /usr/share/", false);
testCommand("Test /usr/share/keyrings Directory", "ls -la /usr/share/keyrings/", false);
testCommand("Test Create Keyrings Directory", "sudo mkdir -p /usr/share/keyrings && echo 'Directory creation successful'");
testCommand("Test Write to Keyrings", "sudo touch /usr/share/keyrings/test-" . uniqid() . " && echo 'Keyring write test successful'");
/**
* Test the specific failing GPG command step by step
*/
echo "<h2>🎯 Specific GPG Key Installation Tests</h2>";
$tempFile = '/tmp/openziti-gpg-test-' . uniqid();
$keyringFile = '/usr/share/keyrings/openziti-test.gpg';
testCommand("Step 1: Download GPG Key", "curl -sSLf https://get.openziti.io/tun/package-repos.gpg -o $tempFile");
testCommand("Step 2: Verify Downloaded File", "ls -la $tempFile && wc -c $tempFile");
testCommand("Step 3: Test GPG Dearmor on File", "sudo gpg --dearmor --output $keyringFile $tempFile");
testCommand("Step 4: Verify Output File", "ls -la $keyringFile", false);
testCommand("Step 5: Test Original Piped Command", "curl -sSLf https://get.openziti.io/tun/package-repos.gpg | sudo gpg --dearmor --output /usr/share/keyrings/openziti-test2.gpg");
// Clean up test files
testCommand("Cleanup: Remove Test Files", "sudo rm -f $tempFile $keyringFile /usr/share/keyrings/openziti-test2.gpg", false);
/**
* Test alternative execution methods
*/
echo "<h2>🔄 Alternative Execution Method Tests</h2>";
// Test direct proc_open
echo "<div class='test-section'>";
echo "<h3>Direct proc_open Test</h3>";
$cmd = "curl -sSLf https://get.openziti.io/tun/package-repos.gpg | head -c 100";
$descriptorspec = [
0 => ['pipe', 'r'],
1 => ['pipe', 'w'],
2 => ['pipe', 'w']
];
$process = proc_open($cmd, $descriptorspec, $pipes);
if (is_resource($process)) {
fclose($pipes[0]);
$stdout = stream_get_contents($pipes[1]);
$stderr = stream_get_contents($pipes[2]);
fclose($pipes[1]);
fclose($pipes[2]);
$return_value = proc_close($process);
echo "<div class='command'>Command: $cmd</div>";
echo "<div class='" . ($return_value === 0 ? 'success' : 'error') . "'>";
echo "<strong>Return Code:</strong> $return_value<br>";
echo "</div>";
echo "<div class='output'>STDOUT: " . substr($stdout, 0, 200) . "\nSTDERR: $stderr</div>";
}
echo "</div>";
/**
* Summary and recommendations
*/
echo "<div class='summary'>";
echo "<h2>📊 Diagnostic Summary</h2>";
$totalTests = count($results);
$successfulTests = count(array_filter($results, function($r) { return $r['success']; }));
$failedTests = $totalTests - $successfulTests;
echo "<p><strong>Total Tests:</strong> $totalTests</p>";
echo "<p><strong>Successful:</strong> $successfulTests</p>";
echo "<p><strong>Failed:</strong> $failedTests</p>";
if (!empty($issues)) {
echo "<h3>🚨 Issues Identified:</h3>";
echo "<ul>";
foreach ($issues as $issue) {
echo "<li>$issue</li>";
}
echo "</ul>";
}
// Generate recommendations based on results
$phpSapi = php_sapi_name();
$currentUser = get_current_user();
$processUid = function_exists('posix_getuid') ? posix_getuid() : null;
echo "<h3>💡 Recommendations:</h3>";
echo "<ul>";
if ($phpSapi === 'fpm-fcgi') {
echo "<li><strong>PHP-FPM Detected:</strong> You're running PHP-FPM which has restricted execution permissions. Consider running the enrollment script via CLI instead.</li>";
}
if ($processUid !== 0 && $currentUser !== 'root') {
echo "<li><strong>Non-Root Execution:</strong> PHP is running as user '$currentUser' (UID: $processUid). Ensure sudo permissions are properly configured for this user.</li>";
}
$sudoTest = array_filter($results, function($r) { return strpos($r['command'], 'sudo -n whoami') !== false; });
if (!empty($sudoTest) && !reset($sudoTest)['success']) {
echo "<li><strong>Sudo Configuration:</strong> Non-interactive sudo failed. Configure passwordless sudo for the web server user or run enrollment via CLI.</li>";
}
$curlTest = array_filter($results, function($r) { return strpos($r['command'], 'curl') !== false && strpos($r['command'], 'openziti') !== false; });
if (!empty($curlTest) && !reset($curlTest)['success']) {
echo "<li><strong>Network Issues:</strong> Cannot reach OpenZiti servers. Check firewall, proxy settings, or DNS resolution.</li>";
}
$gpgTest = array_filter($results, function($r) { return strpos($r['command'], 'gpg --version') !== false; });
if (!empty($gpgTest) && !reset($gpgTest)['success']) {
echo "<li><strong>GPG Missing:</strong> GPG is not installed or not accessible. Install gnupg package.</li>";
}
echo "<li><strong>Alternative Solution:</strong> Consider running the enrollment script directly via SSH as root user instead of through the web interface.</li>";
echo "<li><strong>Web Server Configuration:</strong> If you must use the web interface, configure your web server to run with appropriate permissions or use a different execution method.</li>";
echo "</ul>";
echo "</div>";
// Export results to log file
$logData = [
'timestamp' => date('c'),
'php_sapi' => $phpSapi,
'current_user' => $currentUser,
'process_uid' => $processUid,
'total_tests' => $totalTests,
'successful_tests' => $successfulTests,
'failed_tests' => $failedTests,
'issues' => $issues,
'detailed_results' => $results
];
$logFile = UI_LOG_DIR . '/command-execution-diagnostics-' . date('Y-m-d-H-i-s') . '.json';
if (!is_dir(UI_LOG_DIR)) {
mkdir(UI_LOG_DIR, 0755, true);
}
file_put_contents($logFile, json_encode($logData, JSON_PRETTY_PRINT));
echo "<div class='info'>";
echo "<h3>📄 Detailed Results Saved</h3>";
echo "<p>Complete diagnostic results saved to: <code>$logFile</code></p>";
echo "<a href='?download_log=" . basename($logFile) . "' class='btn'>Download Log File</a>";
echo "</div>";
?>
<div style="margin-top: 30px; text-align: center;">
<a href="dashboard.php" class="btn"> Back to Dashboard</a>
<a href="?refresh=1" class="btn">🔄 Run Diagnostics Again</a>
</div>
</div>
</body>
</html>
<?php
// Handle log file download
if (isset($_GET['download_log'])) {
$logFileName = basename($_GET['download_log']);
$logFilePath = UI_LOG_DIR . '/' . $logFileName;
if (file_exists($logFilePath) && strpos($logFileName, 'command-execution-diagnostics-') === 0) {
header('Content-Type: application/json');
header('Content-Disposition: attachment; filename="' . $logFileName . '"');
header('Content-Length: ' . filesize($logFilePath));
readfile($logFilePath);
exit;
}
}
// Flush output
ob_end_flush();
?>