272 lines
7.7 KiB
PHP
272 lines
7.7 KiB
PHP
<?php
|
|
/**
|
|
* Configuration file for Ziti Router Enrollment UI
|
|
*/
|
|
|
|
// Start session if not already started
|
|
if (session_status() === PHP_SESSION_NONE) {
|
|
session_start();
|
|
}
|
|
|
|
// Application configuration
|
|
define('APP_NAME', 'ZitiNexus Router Enrollment');
|
|
define('APP_VERSION', '1.0.0');
|
|
|
|
// Default API configuration
|
|
define('DEFAULT_API_ENDPOINT', 'https://backend.zitinexus.com');
|
|
|
|
// File paths (matching the bash script)
|
|
define('CONFIG_DIR', '/etc/zitirouter');
|
|
define('CERTS_DIR', CONFIG_DIR . '/certs');
|
|
define('ROUTER_CONFIG', CONFIG_DIR . '/router.yaml');
|
|
define('JWT_FILE', CONFIG_DIR . '/enrollment.jwt');
|
|
define('LOG_FILE', '/var/log/ziti-router-enrollment.log');
|
|
define('SYSTEMD_SERVICE_FILE', '/etc/systemd/system/ziti-router.service');
|
|
|
|
// UI specific paths
|
|
define('UI_LOG_DIR', __DIR__ . '/../logs');
|
|
define('UI_TEMP_DIR', __DIR__ . '/../temp');
|
|
|
|
// Authentication
|
|
define('ADMIN_USERNAME', 'admin');
|
|
define('ADMIN_PASSWORD_HASH', password_hash('admin123', PASSWORD_DEFAULT)); // Change this in production
|
|
|
|
// Security settings
|
|
define('SESSION_TIMEOUT', 3600); // 1 hour
|
|
define('CSRF_TOKEN_NAME', 'csrf_token');
|
|
|
|
// System commands
|
|
define('SYSTEMCTL_CMD', 'systemctl');
|
|
define('HOSTNAME_CMD', 'hostname');
|
|
define('ZITI_CMD', 'ziti');
|
|
|
|
/**
|
|
* Check if user is authenticated
|
|
*/
|
|
function isAuthenticated() {
|
|
return isset($_SESSION['authenticated']) && $_SESSION['authenticated'] === true;
|
|
}
|
|
|
|
/**
|
|
* Check if session is valid
|
|
*/
|
|
function isSessionValid() {
|
|
if (!isset($_SESSION['last_activity'])) {
|
|
return false;
|
|
}
|
|
|
|
if (time() - $_SESSION['last_activity'] > SESSION_TIMEOUT) {
|
|
session_destroy();
|
|
return false;
|
|
}
|
|
|
|
$_SESSION['last_activity'] = time();
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Generate CSRF token
|
|
*/
|
|
function generateCSRFToken() {
|
|
if (!isset($_SESSION[CSRF_TOKEN_NAME])) {
|
|
$_SESSION[CSRF_TOKEN_NAME] = bin2hex(random_bytes(32));
|
|
}
|
|
return $_SESSION[CSRF_TOKEN_NAME];
|
|
}
|
|
|
|
/**
|
|
* Verify CSRF token
|
|
*/
|
|
function verifyCSRFToken($token) {
|
|
return isset($_SESSION[CSRF_TOKEN_NAME]) && hash_equals($_SESSION[CSRF_TOKEN_NAME], $token);
|
|
}
|
|
|
|
/**
|
|
* Sanitize input
|
|
*/
|
|
function sanitizeInput($input) {
|
|
return htmlspecialchars(trim($input), ENT_QUOTES, 'UTF-8');
|
|
}
|
|
|
|
/**
|
|
* Log message to file
|
|
*/
|
|
function logMessage($level, $message) {
|
|
$timestamp = date('Y-m-d H:i:s');
|
|
$logEntry = "[$timestamp] [$level] $message" . PHP_EOL;
|
|
|
|
// Try to write to system log first
|
|
if (is_writable(dirname(LOG_FILE))) {
|
|
file_put_contents(LOG_FILE, $logEntry, FILE_APPEND | LOCK_EX);
|
|
}
|
|
|
|
// Also write to UI log
|
|
$uiLogFile = UI_LOG_DIR . '/ui-enrollment.log';
|
|
if (!is_dir(UI_LOG_DIR)) {
|
|
mkdir(UI_LOG_DIR, 0755, true);
|
|
}
|
|
file_put_contents($uiLogFile, $logEntry, FILE_APPEND | LOCK_EX);
|
|
}
|
|
|
|
/**
|
|
* Check if running as root/admin or has sudo privileges
|
|
*/
|
|
function isRunningAsRoot() {
|
|
// If actually running as root
|
|
if (posix_getuid() === 0) {
|
|
return true;
|
|
}
|
|
|
|
// Test if we have sudo privileges by trying a simple sudo command
|
|
$output = '';
|
|
$returnCode = 0;
|
|
$testCommand = 'sudo -n whoami 2>/dev/null';
|
|
|
|
$descriptorspec = [
|
|
0 => ['pipe', 'r'],
|
|
1 => ['pipe', 'w'],
|
|
2 => ['pipe', 'w']
|
|
];
|
|
|
|
$process = proc_open($testCommand, $descriptorspec, $pipes);
|
|
|
|
if (is_resource($process)) {
|
|
fclose($pipes[0]);
|
|
$stdout = stream_get_contents($pipes[1]);
|
|
fclose($pipes[1]);
|
|
fclose($pipes[2]);
|
|
$returnCode = proc_close($process);
|
|
|
|
// If sudo command succeeded, we have sudo privileges
|
|
return $returnCode === 0;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Execute system command safely with automatic sudo for privileged operations
|
|
*/
|
|
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', 'cat', 'openssl'
|
|
];
|
|
|
|
// Check if command needs sudo and doesn't already have it
|
|
$needsSudo = false;
|
|
$commandParts = explode(' ', trim($command));
|
|
$baseCommand = $commandParts[0];
|
|
|
|
// 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;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Also check for file operations in system directories
|
|
if (strpos($command, '/etc/') !== false ||
|
|
strpos($command, '/var/') !== false ||
|
|
strpos($command, '/usr/') !== false ||
|
|
strpos($command, '/opt/') !== false) {
|
|
$needsSudo = true;
|
|
}
|
|
}
|
|
|
|
// Add sudo if needed and we're not already root
|
|
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
|
|
];
|
|
|
|
// 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]);
|
|
|
|
$stdout = stream_get_contents($pipes[1]);
|
|
$stderr = stream_get_contents($pipes[2]);
|
|
|
|
fclose($pipes[1]);
|
|
fclose($pipes[2]);
|
|
|
|
$returnCode = proc_close($process);
|
|
$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;
|
|
}
|
|
|
|
/**
|
|
* Get the correct asset path based on current directory structure
|
|
*/
|
|
function getAssetPath($asset) {
|
|
// Clean the asset path
|
|
$asset = ltrim($asset, '/');
|
|
|
|
// Get the current script's directory and the request URI
|
|
$scriptDir = dirname($_SERVER['SCRIPT_FILENAME']);
|
|
$requestUri = $_SERVER['REQUEST_URI'];
|
|
$scriptName = $_SERVER['SCRIPT_NAME'];
|
|
|
|
// Check if we're accessing files from the public directory
|
|
// but the document root is set to the main UI directory
|
|
if (strpos($scriptName, '/public/') !== false ||
|
|
strpos($requestUri, '/public/') !== false ||
|
|
basename($scriptDir) === 'public') {
|
|
// We're in the public directory context, use relative paths
|
|
return '../assets/' . $asset;
|
|
} else {
|
|
// We're in the main directory context, use direct paths
|
|
return 'assets/' . $asset;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get base URL for the application
|
|
*/
|
|
function getBaseUrl() {
|
|
$protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https' : 'http';
|
|
$host = $_SERVER['HTTP_HOST'];
|
|
$scriptName = $_SERVER['SCRIPT_NAME'];
|
|
|
|
// Remove the script filename to get the base path
|
|
$basePath = dirname($scriptName);
|
|
if ($basePath === '/') {
|
|
$basePath = '';
|
|
}
|
|
|
|
return $protocol . '://' . $host . $basePath;
|
|
}
|
|
?>
|