Add Arch Linux server support and fix package sanitization
- Add Arch Linux (pacman) support to server operations: CheckUpdates, InstallDocker, InstallPrerequisites, UpdatePackage - Implement parsePacmanOutput() to parse 'pacman -Qu' output format - Add security improvement: package name sanitization to prevent command injection - Initialize variables in CheckUpdates to prevent undefined variable errors in catch block - Use proper Arch pacman flags: -Syu for full system upgrade before operations 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
a5b13b57cc
commit
9bb77da9a4
4 changed files with 94 additions and 3 deletions
|
|
@ -13,6 +13,9 @@ class CheckUpdates
|
|||
|
||||
public function handle(Server $server)
|
||||
{
|
||||
$osId = 'unknown';
|
||||
$packageManager = null;
|
||||
|
||||
try {
|
||||
if ($server->serverStatus() === false) {
|
||||
return [
|
||||
|
|
@ -93,6 +96,16 @@ public function handle(Server $server)
|
|||
$out['osId'] = $osId;
|
||||
$out['package_manager'] = $packageManager;
|
||||
|
||||
return $out;
|
||||
case 'pacman':
|
||||
// Sync database first, then check for updates
|
||||
// Using -Sy to refresh package database before querying available updates
|
||||
instant_remote_process(['pacman -Sy'], $server);
|
||||
$output = instant_remote_process(['pacman -Qu 2>/dev/null'], $server);
|
||||
$out = $this->parsePacmanOutput($output);
|
||||
$out['osId'] = $osId;
|
||||
$out['package_manager'] = $packageManager;
|
||||
|
||||
return $out;
|
||||
default:
|
||||
return [
|
||||
|
|
@ -219,4 +232,45 @@ private function parseAptOutput(string $output): array
|
|||
'updates' => $updates,
|
||||
];
|
||||
}
|
||||
|
||||
private function parsePacmanOutput(string $output): array
|
||||
{
|
||||
$updates = [];
|
||||
$unparsedLines = [];
|
||||
$lines = explode("\n", $output);
|
||||
|
||||
foreach ($lines as $line) {
|
||||
if (empty($line)) {
|
||||
continue;
|
||||
}
|
||||
// Format: package current_version -> new_version
|
||||
if (preg_match('/^(\S+)\s+(\S+)\s+->\s+(\S+)$/', $line, $matches)) {
|
||||
$updates[] = [
|
||||
'package' => $matches[1],
|
||||
'current_version' => $matches[2],
|
||||
'new_version' => $matches[3],
|
||||
'architecture' => 'unknown',
|
||||
'repository' => 'unknown',
|
||||
];
|
||||
} else {
|
||||
// Log unmatched lines for debugging purposes
|
||||
$unparsedLines[] = $line;
|
||||
}
|
||||
}
|
||||
|
||||
$result = [
|
||||
'total_updates' => count($updates),
|
||||
'updates' => $updates,
|
||||
];
|
||||
|
||||
// Include unparsed lines in the result for debugging if any exist
|
||||
if (! empty($unparsedLines)) {
|
||||
$result['unparsed_lines'] = $unparsedLines;
|
||||
\Illuminate\Support\Facades\Log::debug('Pacman output contained unparsed lines', [
|
||||
'unparsed_lines' => $unparsedLines,
|
||||
]);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -78,6 +78,8 @@ public function handle(Server $server)
|
|||
$command = $command->merge([$this->getRhelDockerInstallCommand()]);
|
||||
} elseif ($supported_os_type->contains('sles')) {
|
||||
$command = $command->merge([$this->getSuseDockerInstallCommand()]);
|
||||
} elseif ($supported_os_type->contains('arch')) {
|
||||
$command = $command->merge([$this->getArchDockerInstallCommand()]);
|
||||
} else {
|
||||
$command = $command->merge([$this->getGenericDockerInstallCommand()]);
|
||||
}
|
||||
|
|
@ -150,4 +152,14 @@ private function getGenericDockerInstallCommand(): string
|
|||
{
|
||||
return "curl https://releases.rancher.com/install-docker/{$this->dockerVersion}.sh | sh || curl https://get.docker.com | sh -s -- --version {$this->dockerVersion}";
|
||||
}
|
||||
|
||||
private function getArchDockerInstallCommand(): string
|
||||
{
|
||||
// Use -Syu to perform full system upgrade before installing Docker
|
||||
// Partial upgrades (-Sy without -u) are discouraged on Arch Linux
|
||||
// as they can lead to broken dependencies and system instability
|
||||
return 'pacman -Syu --noconfirm docker docker-compose && '.
|
||||
'systemctl enable docker.service && '.
|
||||
'systemctl start docker.service';
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,6 +46,13 @@ public function handle(Server $server)
|
|||
'command -v git >/dev/null || zypper install -y git',
|
||||
'command -v jq >/dev/null || zypper install -y jq',
|
||||
]);
|
||||
} elseif ($supported_os_type->contains('arch')) {
|
||||
// Use -Syu for full system upgrade to avoid partial upgrade issues on Arch Linux
|
||||
// --needed flag skips packages that are already installed and up-to-date
|
||||
$command = $command->merge([
|
||||
"echo 'Installing Prerequisites for Arch Linux...'",
|
||||
'pacman -Syu --noconfirm --needed curl wget git jq',
|
||||
]);
|
||||
} else {
|
||||
throw new \Exception('Unsupported OS type for prerequisites installation');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,18 +20,36 @@ public function handle(Server $server, string $osId, ?string $package = null, ?s
|
|||
'error' => 'Server is not reachable or not ready.',
|
||||
];
|
||||
}
|
||||
|
||||
// Sanitize package name to prevent command injection
|
||||
// Only allow alphanumeric characters, hyphens, underscores, periods, plus signs, and colons
|
||||
// These are valid characters in package names across most package managers
|
||||
$sanitizedPackage = '';
|
||||
if ($package !== null && ! $all) {
|
||||
if (! preg_match('/^[a-zA-Z0-9._+:-]+$/', $package)) {
|
||||
return [
|
||||
'error' => 'Invalid package name. Package names can only contain alphanumeric characters, hyphens, underscores, periods, plus signs, and colons.',
|
||||
];
|
||||
}
|
||||
$sanitizedPackage = escapeshellarg($package);
|
||||
}
|
||||
|
||||
switch ($packageManager) {
|
||||
case 'zypper':
|
||||
$commandAll = 'zypper update -y';
|
||||
$commandInstall = 'zypper install -y '.$package;
|
||||
$commandInstall = 'zypper install -y '.$sanitizedPackage;
|
||||
break;
|
||||
case 'dnf':
|
||||
$commandAll = 'dnf update -y';
|
||||
$commandInstall = 'dnf update -y '.$package;
|
||||
$commandInstall = 'dnf update -y '.$sanitizedPackage;
|
||||
break;
|
||||
case 'apt':
|
||||
$commandAll = 'apt update && apt upgrade -y';
|
||||
$commandInstall = 'apt install -y '.$package;
|
||||
$commandInstall = 'apt install -y '.$sanitizedPackage;
|
||||
break;
|
||||
case 'pacman':
|
||||
$commandAll = 'pacman -Syu --noconfirm';
|
||||
$commandInstall = 'pacman -S --noconfirm '.$sanitizedPackage;
|
||||
break;
|
||||
default:
|
||||
return [
|
||||
|
|
|
|||
Loading…
Reference in a new issue