fixed script new7

This commit is contained in:
Edmund Tan 2025-07-23 00:21:32 +08:00
parent 951a66417d
commit 03ba182fb8
3 changed files with 111 additions and 610 deletions

View File

@ -179,41 +179,23 @@ class EnrollmentManager {
return true;
}
$this->reportProgress('INSTALL', 'Setting up OpenZiti package repository...');
$this->reportProgress('INSTALL', 'Installing OpenZiti CLI from pre-configured repository...');
// Add GPG key using enhanced method to handle PHP execution environment
if (!$this->addOpenZitiGpgKey()) {
throw new Exception('Failed to add OpenZiti GPG key');
// Verify repository is configured
if (!file_exists('/etc/apt/sources.list.d/openziti-release.list')) {
throw new Exception('OpenZiti repository not configured. Please run install.sh first to set up the system.');
}
// Set proper permissions
if (!executeCommand('chmod a+r /usr/share/keyrings/openziti.gpg')) {
throw new Exception('Failed to set GPG key permissions');
if (!file_exists('/usr/share/keyrings/openziti.gpg')) {
throw new Exception('OpenZiti GPG key not found. Please run install.sh first to set up the system.');
}
// Add repository to sources list
$repoContent = 'deb [signed-by=/usr/share/keyrings/openziti.gpg] https://packages.openziti.org/zitipax-openziti-deb-stable debian main';
$tempFile = tempnam(sys_get_temp_dir(), 'openziti-repo');
file_put_contents($tempFile, $repoContent);
if (!executeCommand("cp '$tempFile' /etc/apt/sources.list.d/openziti-release.list")) {
unlink($tempFile);
throw new Exception('Failed to add OpenZiti repository');
}
unlink($tempFile);
// Update package list
$this->reportProgress('INSTALL', 'Updating package list...');
if (!executeCommand('apt-get update')) {
throw new Exception('Failed to update package list');
}
// Install openziti-router package
// Install openziti-router package from pre-configured repository
$this->reportProgress('INSTALL', 'Installing openziti-router package...');
if (!executeCommand('apt-get install -y openziti-router')) {
$this->reportProgress('INSTALL', 'Trying to install ziti CLI only...');
if (!executeCommand('apt-get install -y ziti')) {
throw new Exception('Failed to install OpenZiti CLI');
throw new Exception('Failed to install OpenZiti CLI. Repository may not be properly configured. Please run install.sh first.');
}
}
@ -528,191 +510,6 @@ EOF;
);
}
/**
* Add OpenZiti GPG key with enhanced error handling for CloudStack environments
*/
private function addOpenZitiGpgKey() {
$gpgKeyUrl = 'https://get.openziti.io/tun/package-repos.gpg';
$gpgKeyPath = '/usr/share/keyrings/openziti.gpg';
// First, check if GPG key already exists and is valid
if (file_exists($gpgKeyPath) && filesize($gpgKeyPath) > 0) {
$this->reportProgress('INSTALL', 'OpenZiti GPG key already exists (' . filesize($gpgKeyPath) . ' bytes), skipping installation');
logMessage('INFO', 'GPG key already exists at: ' . $gpgKeyPath);
return true;
}
$this->reportProgress('INSTALL', 'Installing OpenZiti GPG key...');
// Ensure keyrings directory exists with proper permissions
if (!$this->ensureKeyringsDirectory()) {
logMessage('ERROR', 'Failed to create keyrings directory');
return false;
}
// Method 1: CloudStack-optimized approach - download and process separately
$this->reportProgress('INSTALL', 'Downloading GPG key...');
$tempGpgFile = tempnam(sys_get_temp_dir(), 'openziti-gpg');
// Step 1: Download GPG key with detailed error reporting
$downloadCommand = 'curl -sSLf --connect-timeout 30 --max-time 60 ' . $gpgKeyUrl . ' -o ' . $tempGpgFile;
$output = '';
if (!executeCommand($downloadCommand, $output)) {
@unlink($tempGpgFile);
$errorMsg = 'Failed to download GPG key from ' . $gpgKeyUrl . '. Error: ' . $output;
logMessage('ERROR', $errorMsg);
$this->reportProgress('INSTALL', 'Download failed: ' . $output);
return false;
}
// Step 2: Verify downloaded file
if (!file_exists($tempGpgFile) || filesize($tempGpgFile) == 0) {
@unlink($tempGpgFile);
$errorMsg = 'Downloaded GPG key file is empty or missing';
logMessage('ERROR', $errorMsg);
$this->reportProgress('INSTALL', $errorMsg);
return false;
}
$fileSize = filesize($tempGpgFile);
$this->reportProgress('INSTALL', "GPG key downloaded successfully ($fileSize bytes), processing...");
logMessage('INFO', "Downloaded GPG key: $fileSize bytes to $tempGpgFile");
// Step 3: Try multiple processing methods with detailed error reporting
$methods = [
'sudo_gpg_dearmor' => [
'name' => 'Sudo GPG dearmor',
'command' => "sudo /usr/bin/gpg --dearmor --output '$gpgKeyPath' '$tempGpgFile'"
],
'direct_gpg_dearmor' => [
'name' => 'Direct GPG dearmor',
'command' => "/usr/bin/gpg --dearmor --output '$gpgKeyPath' '$tempGpgFile'"
],
'sudo_cat_pipe' => [
'name' => 'Sudo cat pipe',
'command' => "sudo bash -c 'cat $tempGpgFile | /usr/bin/gpg --dearmor > $gpgKeyPath'"
],
'sudo_redirect' => [
'name' => 'Sudo redirect',
'command' => "sudo bash -c '/usr/bin/gpg --dearmor < $tempGpgFile > $gpgKeyPath'"
],
'python_base64' => [
'name' => 'Python base64 decode',
'command' => "sudo python3 -c \"import base64; open('$gpgKeyPath', 'wb').write(base64.b64decode(open('$tempGpgFile', 'rb').read()))\""
]
];
foreach ($methods as $methodKey => $method) {
$this->reportProgress('INSTALL', "Trying method: {$method['name']}...");
logMessage('INFO', "Attempting GPG processing method: {$method['name']}");
$output = '';
if (executeCommand($method['command'], $output)) {
// Verify the processed file exists and has content
if (file_exists($gpgKeyPath) && filesize($gpgKeyPath) > 0) {
@unlink($tempGpgFile);
$processedSize = filesize($gpgKeyPath);
$this->reportProgress('INSTALL', "GPG key processed successfully using {$method['name']} ($processedSize bytes)");
logMessage('INFO', "GPG key successfully processed: $processedSize bytes at $gpgKeyPath");
return true;
} else {
logMessage('WARNING', "Method {$method['name']} completed but output file is missing or empty");
}
} else {
logMessage('WARNING', "Method {$method['name']} failed: $output");
}
}
// Method 4: Last resort - try to use the raw file directly
$this->reportProgress('INSTALL', 'Trying raw file copy as last resort...');
logMessage('INFO', 'Attempting raw file copy as final fallback');
if (executeCommand("sudo cp '$tempGpgFile' '$gpgKeyPath'", $output)) {
if (file_exists($gpgKeyPath) && filesize($gpgKeyPath) > 0) {
@unlink($tempGpgFile);
$this->reportProgress('INSTALL', 'GPG key copied as raw file - apt will handle format conversion');
logMessage('INFO', 'GPG key copied as raw file for apt to process');
return true;
}
}
// Clean up and report final failure
@unlink($tempGpgFile);
$errorMsg = 'All GPG key installation methods failed. Check system permissions and network connectivity.';
logMessage('ERROR', $errorMsg);
$this->reportProgress('INSTALL', $errorMsg);
// Additional diagnostic information
$this->logDiagnosticInfo();
return false;
}
/**
* Ensure keyrings directory exists with proper permissions
*/
private function ensureKeyringsDirectory() {
$keyringsDir = '/usr/share/keyrings';
// Check if directory exists
if (is_dir($keyringsDir)) {
logMessage('INFO', 'Keyrings directory already exists');
return true;
}
// Try to create directory
$output = '';
if (executeCommand("sudo mkdir -p '$keyringsDir'", $output)) {
if (executeCommand("sudo chmod 755 '$keyringsDir'", $output)) {
logMessage('INFO', 'Keyrings directory created successfully');
return true;
} else {
logMessage('ERROR', 'Failed to set keyrings directory permissions: ' . $output);
return false;
}
} else {
logMessage('ERROR', 'Failed to create keyrings directory: ' . $output);
return false;
}
}
/**
* Log diagnostic information for troubleshooting
*/
private function logDiagnosticInfo() {
$diagnostics = [];
// Check basic commands
$commands = ['curl', 'gpg', 'python3', 'sudo'];
foreach ($commands as $cmd) {
$output = '';
$available = executeCommand("which $cmd", $output) ? 'available' : 'not found';
$diagnostics[] = "$cmd: $available";
}
// Check permissions
$output = '';
executeCommand('id', $output);
$diagnostics[] = "Current user: " . trim($output);
// Check sudo permissions
$output = '';
executeCommand('sudo -l | grep gpg', $output);
$diagnostics[] = "GPG sudo permissions: " . (empty(trim($output)) ? 'none found' : 'available');
// Check network connectivity
$output = '';
$networkOk = executeCommand('curl -I --connect-timeout 5 https://get.openziti.io', $output) ? 'working' : 'failed';
$diagnostics[] = "Network connectivity: $networkOk";
// Check disk space
$output = '';
executeCommand('df -h /usr/share', $output);
$diagnostics[] = "Disk space: " . trim($output);
logMessage('INFO', 'GPG Installation Diagnostics: ' . implode('; ', $diagnostics));
}
/**
* Check if command exists

View File

@ -337,6 +337,106 @@ configure_php() {
log "SUCCESS" "PHP configured successfully"
}
# Set up OpenZiti package repository
setup_openziti_repository() {
log "INFO" "Setting up OpenZiti package repository..."
local gpgKeyUrl='https://get.openziti.io/tun/package-repos.gpg'
local gpgKeyPath='/usr/share/keyrings/openziti.gpg'
# Check if GPG key already exists and is valid
if [[ -f "$gpgKeyPath" && -s "$gpgKeyPath" ]]; then
local keySize=$(wc -c < "$gpgKeyPath")
log "SUCCESS" "OpenZiti GPG key already exists ($keySize bytes), skipping installation"
else
log "INFO" "Installing OpenZiti GPG key..."
# Ensure keyrings directory exists
mkdir -p /usr/share/keyrings || error_exit "Failed to create keyrings directory"
chmod 755 /usr/share/keyrings || error_exit "Failed to set keyrings directory permissions"
# Download GPG key to temporary file
local tempGpgFile=$(mktemp)
log "INFO" "Downloading GPG key from $gpgKeyUrl..."
if curl -sSLf --connect-timeout 30 --max-time 60 "$gpgKeyUrl" -o "$tempGpgFile"; then
local fileSize=$(wc -c < "$tempGpgFile")
log "SUCCESS" "GPG key downloaded successfully ($fileSize bytes)"
# Try multiple methods to process the GPG key
local methods=(
"gpg --dearmor --output '$gpgKeyPath' '$tempGpgFile'"
"cat '$tempGpgFile' | gpg --dearmor > '$gpgKeyPath'"
"gpg --dearmor < '$tempGpgFile' > '$gpgKeyPath'"
)
local success=false
for method in "${methods[@]}"; do
log "INFO" "Trying GPG processing method: $method"
if eval "$method" 2>/dev/null; then
if [[ -f "$gpgKeyPath" && -s "$gpgKeyPath" ]]; then
local processedSize=$(wc -c < "$gpgKeyPath")
log "SUCCESS" "GPG key processed successfully ($processedSize bytes)"
success=true
break
fi
fi
done
# Fallback: copy raw file and let apt handle it
if [[ "$success" != true ]]; then
log "WARNING" "GPG processing failed, trying raw file copy..."
if cp "$tempGpgFile" "$gpgKeyPath"; then
log "SUCCESS" "GPG key copied as raw file - apt will handle format conversion"
success=true
fi
fi
rm -f "$tempGpgFile"
if [[ "$success" != true ]]; then
error_exit "Failed to install OpenZiti GPG key"
fi
else
rm -f "$tempGpgFile"
error_exit "Failed to download OpenZiti GPG key from $gpgKeyUrl"
fi
fi
# Set proper permissions on GPG key
chmod a+r "$gpgKeyPath" || error_exit "Failed to set GPG key permissions"
# Configure OpenZiti repository
local repoFile='/etc/apt/sources.list.d/openziti-release.list'
local repoContent='deb [signed-by=/usr/share/keyrings/openziti.gpg] https://packages.openziti.org/zitipax-openziti-deb-stable debian main'
if [[ -f "$repoFile" ]]; then
log "INFO" "OpenZiti repository already configured"
else
log "INFO" "Configuring OpenZiti repository..."
echo "$repoContent" > "$repoFile" || error_exit "Failed to create repository file"
log "SUCCESS" "OpenZiti repository configured"
fi
# Update package list
log "INFO" "Updating package list..."
if apt update >/dev/null 2>&1; then
log "SUCCESS" "Package list updated successfully"
else
log "WARNING" "Package list update had issues, but continuing..."
fi
# Verify repository is accessible
log "INFO" "Verifying OpenZiti repository accessibility..."
if apt-cache show openziti-router >/dev/null 2>&1; then
log "SUCCESS" "OpenZiti repository is accessible and openziti-router package is available"
elif apt-cache show ziti >/dev/null 2>&1; then
log "SUCCESS" "OpenZiti repository is accessible and ziti package is available"
else
log "WARNING" "OpenZiti packages not found in repositories, but repository is configured"
fi
}
# Set up sudo access
setup_sudo() {
log "INFO" "Setting up comprehensive sudo access for web server..."
@ -571,6 +671,9 @@ main() {
# Set up sudo access
setup_sudo
# Set up OpenZiti package repository
setup_openziti_repository
# Update hosts file
update_hosts

View File

@ -1,399 +0,0 @@
<?php
/**
* Pre-Enrollment Check Script
* Verifies system readiness before attempting router enrollment
*/
require_once 'includes/config.php';
// Set content type for web access
if (php_sapi_name() !== 'cli') {
header('Content-Type: text/html; charset=UTF-8');
}
/**
* Execute command and return detailed result
*/
function checkCommand($command, $description) {
$startTime = microtime(true);
$output = '';
$returnCode = 0;
exec($command . ' 2>&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) {
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Pre-Enrollment System Check</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); }
.section { margin: 20px 0; padding: 15px; border: 1px solid #ddd; border-radius: 5px; }
.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; }
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; }
.status-ok { color: #28a745; font-weight: bold; }
.status-fail { color: #dc3545; font-weight: bold; }
.status-warn { color: #ffc107; font-weight: bold; }
</style>
</head>
<body>
<div class="container">
<h1>🔍 Pre-Enrollment System Check</h1>
<p><strong>Purpose:</strong> Verify system readiness for ZitiNexus Router enrollment</p>
<p><strong>Time:</strong> <?php echo $results['timestamp']; ?></p>
<!-- Environment Information -->
<div class="section info">
<h3>📋 Environment Information</h3>
<table>
<?php foreach ($results['environment'] as $key => $value): ?>
<tr>
<td><?php echo ucwords(str_replace('_', ' ', $key)); ?></td>
<td><?php echo htmlspecialchars($value); ?></td>
</tr>
<?php endforeach; ?>
</table>
</div>
<!-- Command Availability -->
<div class="section">
<h3>🔧 Command Availability</h3>
<table>
<tr><th>Command</th><th>Status</th><th>Details</th></tr>
<?php foreach ($results['commands'] as $name => $result): ?>
<?php if (strpos($name, '_version') !== false) continue; ?>
<tr>
<td><?php echo htmlspecialchars($name); ?></td>
<td class="<?php echo $result['success'] ? 'status-ok' : 'status-fail'; ?>">
<?php echo $result['success'] ? '✅ Available' : '❌ Not Found'; ?>
</td>
<td>
<?php if ($result['success'] && isset($results['commands'][$name . '_version'])): ?>
<?php echo htmlspecialchars(trim(explode("\n", $results['commands'][$name . '_version']['output'])[0])); ?>
<?php else: ?>
<?php echo htmlspecialchars($result['output']); ?>
<?php endif; ?>
</td>
</tr>
<?php endforeach; ?>
</table>
</div>
<!-- Permissions Check -->
<div class="section">
<h3>🔐 Permissions Check</h3>
<?php foreach ($results['permissions'] as $name => $result): ?>
<div class="command"><?php echo htmlspecialchars($result['command']); ?></div>
<div class="<?php echo $result['success'] ? 'success' : 'error'; ?>">
<strong>Status:</strong> <?php echo $result['success'] ? '✅ SUCCESS' : '❌ FAILED'; ?><br>
<strong>Return Code:</strong> <?php echo $result['returnCode']; ?><br>
<strong>Duration:</strong> <?php echo $result['duration']; ?>
</div>
<?php if (!empty($result['output'])): ?>
<div class="output"><?php echo htmlspecialchars($result['output']); ?></div>
<?php endif; ?>
<?php endforeach; ?>
</div>
<!-- Network Connectivity -->
<div class="section">
<h3>🌐 Network Connectivity</h3>
<?php foreach ($results['network'] as $name => $result): ?>
<div class="command"><?php echo htmlspecialchars($result['command']); ?></div>
<div class="<?php echo $result['success'] ? 'success' : 'warning'; ?>">
<strong>Status:</strong> <?php echo $result['success'] ? '✅ SUCCESS' : '⚠️ FAILED'; ?><br>
<strong>Return Code:</strong> <?php echo $result['returnCode']; ?><br>
<strong>Duration:</strong> <?php echo $result['duration']; ?>
</div>
<?php if (!empty($result['output'])): ?>
<div class="output"><?php echo htmlspecialchars(substr($result['output'], 0, 500)) . (strlen($result['output']) > 500 ? '...' : ''); ?></div>
<?php endif; ?>
<?php endforeach; ?>
</div>
<!-- File System Status -->
<div class="section">
<h3>📁 File System Status</h3>
<table>
<tr><th>Path</th><th>Status</th><th>Size</th><th>Permissions</th><th>Description</th></tr>
<?php foreach ($results['files'] as $path => $info): ?>
<tr>
<td><?php echo htmlspecialchars($path); ?></td>
<td class="<?php echo $info['exists'] ? 'status-ok' : 'status-warn'; ?>">
<?php echo $info['exists'] ? '✅ Exists' : '⚠️ Missing'; ?>
</td>
<td><?php echo $info['size'] > 0 ? number_format($info['size']) . ' bytes' : '-'; ?></td>
<td><?php echo $info['permissions'] ?: '-'; ?></td>
<td><?php echo htmlspecialchars($info['description']); ?></td>
</tr>
<?php endforeach; ?>
</table>
</div>
<!-- Recommendations -->
<div class="section">
<h3>💡 Recommendations</h3>
<?php if (empty($results['recommendations'])): ?>
<div class="success">
<strong> System appears ready for enrollment!</strong><br>
No critical issues detected.
</div>
<?php else: ?>
<?php foreach ($results['recommendations'] as $rec): ?>
<div class="<?php echo $rec['type']; ?>">
<strong><?php echo ucfirst($rec['type']); ?>:</strong> <?php echo htmlspecialchars($rec['message']); ?><br>
<strong>Action:</strong> <?php echo htmlspecialchars($rec['action']); ?>
</div>
<?php endforeach; ?>
<?php endif; ?>
</div>
<!-- Next Steps -->
<div class="section info">
<h3>🚀 Next Steps</h3>
<ol>
<li><strong>Address any errors or warnings</strong> shown in the recommendations above</li>
<li><strong>Run fix-permissions.sh</strong> if sudo access is not working: <code>sudo ./fix-permissions.sh</code></li>
<li><strong>Try the enrollment process</strong> once all critical issues are resolved</li>
<li><strong>Check the logs</strong> in <code>/var/www/ziti-enrollment/logs/</code> if enrollment fails</li>
</ol>
</div>
</div>
</body>
</html>
<?php
}
// Run the checks and output results
$results = runPreEnrollmentChecks();
if (php_sapi_name() === 'cli') {
// CLI output
echo "Pre-Enrollment System Check\n";
echo "===========================\n\n";
echo "Environment: " . $results['environment']['php_sapi'] . " (PHP " . $results['environment']['php_version'] . ")\n";
echo "User: " . $results['environment']['user'] . " (UID: " . $results['environment']['uid'] . ")\n\n";
echo "Recommendations:\n";
foreach ($results['recommendations'] as $rec) {
echo "- [{$rec['type']}] {$rec['message']}\n";
echo " Action: {$rec['action']}\n\n";
}
} else {
// Web output
outputHTML($results);
}
?>