common_name); if ($isArchive) { $cdnUrl = Storage::disk('r2-public')->url("ca/archives/{$cert->uuid}/{$slug}.crt"); } else { $cdnUrl = Storage::disk('r2-public')->url("ca/{$slug}.crt"); } $typeLabel = $cert->ca_type === 'root' ? 'Root' : 'Intermediate'; $store = $cert->ca_type === 'root' ? 'Root' : 'CA'; $cleanName = $cert->common_name; // Hybrid Batch + PowerShell script for rich UI return "@echo off\r\n" . "setlocal\r\n" . "title TrustLab CA Installer\r\n" . "call :printHeader\r\n" . "\r\n" . "echo.\r\n" . "call :printInfo \"Initiating installation for: {$cleanName} ({$typeLabel})\"\r\n" . "\r\n" . "set \"TEMP_CERT=%TEMP%\\trustlab-ca-{$cert->uuid}.crt\"\r\n" . "\r\n" . "call :printAction \"Downloading CA certificate...\"\r\n" . "powershell -Command \"Invoke-WebRequest -Uri '{$cdnUrl}' -OutFile '%TEMP_CERT%'\"\r\n" . "if %ERRORLEVEL% NEQ 0 (\r\n" . " call :printError \"Failed to download certificate.\"\r\n" . " pause\r\n" . " exit /b 1\r\n" . ")\r\n" . "call :printSuccess \"Download complete.\"\r\n" . "\r\n" . "call :printAction \"Installing to Windows Certificate Store ({$store})...\"\r\n" . "certutil -addstore -f \"{$store}\" \"%TEMP_CERT%\" >nul 2>&1\r\n" . "if %ERRORLEVEL% NEQ 0 (\r\n" . " call :printError \"Failed to install certificate to store.\"\r\n" . " del \"%TEMP_CERT%\"\r\n" . " pause\r\n" . " exit /b 1\r\n" . ")\r\n" . "call :printSuccess \"Certificate installed successfully!\"\r\n" . "\r\n" . "powershell -Command \"Invoke-WebRequest -Uri '" . config('app.url') . "/api/public/ca-certificates/{$cert->serial_number}/track' -Method POST -ErrorAction SilentlyContinue\" >nul 2>&1\r\n" . "\r\n" . "del \"%TEMP_CERT%\"\r\n" . "echo.\r\n" . "call :printInfo \"Press any key to close...\"\r\n" . "pause >nul\r\n" . "exit /b\r\n" . "\r\n" . ":printHeader\r\n" . "cls\r\n" . "powershell -Command \"Write-Host ' _______ _____ _ _ _____ _______ _ _______ ______ ' -ForegroundColor Cyan\"\r\n" . "powershell -Command \"Write-Host ' |__ __|| __ \| | | |/ ____||__ __|| | |__ __|| _ |' -ForegroundColor Cyan\"\r\n" . "powershell -Command \"Write-Host ' | | | |__) || | | || (___ | | | | | | | |_) |' -ForegroundColor Cyan\"\r\n" . "powershell -Command \"Write-Host ' | | | _ / | | | | \___ \ | | | | | | | _ < ' -ForegroundColor Cyan\"\r\n" . "powershell -Command \"Write-Host ' | | | | \ \ | |__| | ____) | | | | |____ | | | |_) |' -ForegroundColor Cyan\"\r\n" . "powershell -Command \"Write-Host ' |_| |_| \_\| \____/ |_____/ |_| |______| |_| |______|' -ForegroundColor Cyan\"\r\n" . "powershell -Command \"Write-Host ' '\"\r\n" . "exit /b\r\n" . "\r\n" . ":printInfo\r\n" . "powershell -Command \"Write-Host ' [ INFO ] %~1' -ForegroundColor Cyan\"\r\n" . "exit /b\r\n" . "\r\n" . ":printAction\r\n" . "powershell -Command \"Write-Host ' [ .... ] %~1' -ForegroundColor Yellow\"\r\n" . "exit /b\r\n" . "\r\n" . ":printSuccess\r\n" . "powershell -Command \"Write-Host ' [ OK ] %~1' -ForegroundColor Green\"\r\n" . "exit /b\r\n" . "\r\n" . ":printError\r\n" . "powershell -Command \"Write-Host ' [ FAIL ] %~1' -ForegroundColor Red\"\r\n" . "exit /b\r\n"; } /** * Generate macOS Configuration Profile (.mobileconfig) */ public function generateMacInstaller(CaCertificate $cert): string { $certBase64 = base64_encode($cert->cert_content); $payloadId = "com.trustlab.ca." . Str::slug($cert->common_name); $uuid1 = Str::uuid()->toString(); $uuid2 = Str::uuid()->toString(); // Root CAs use 'com.apple.security.root', Intermediate CAs use 'com.apple.security.pkcs1' (intermediate) $payloadType = $cert->ca_type === 'root' ? 'com.apple.security.root' : 'com.apple.security.pkcs1'; return "\n" . "\n" . "\n" . "\n" . " PayloadContent\n" . " \n" . " \n" . " PayloadCertificateFileName\n" . " {$cert->common_name}.crt\n" . " PayloadContent\n" . " {$certBase64}\n" . " PayloadDescription\n" . " TrustLab CA Certificate\n" . " PayloadDisplayName\n" . " {$cert->common_name}\n" . " PayloadIdentifier\n" . " {$payloadId}.cert\n" . " PayloadType\n" . " {$payloadType}\n" . " PayloadUUID\n" . " {$uuid2}\n" . " PayloadVersion\n" . " 1\n" . " \n" . " \n" . " PayloadDescription\n" . " TrustLab CA Installation\n" . " PayloadDisplayName\n" . " TrustLab CA: {$cert->common_name}\n" . " PayloadIdentifier\n" . " {$payloadId}\n" . " PayloadRemovalDisallowed\n" . " \n" . " PayloadType\n" . " Configuration\n" . " PayloadUUID\n" . " {$uuid1}\n" . " PayloadVersion\n" . " 1\n" . "\n" . ""; } /** * Generate Linux Installer (.sh) with Proxmox-style Aesthetics */ public function generateLinuxInstaller(CaCertificate $cert, bool $isArchive = false): string { $slug = Str::slug($cert->common_name); if ($isArchive) { $cdnUrl = Storage::disk('r2-public')->url("ca/archives/{$cert->uuid}/{$slug}.crt"); } else { $cdnUrl = Storage::disk('r2-public')->url("ca/{$slug}.crt"); } $filename = "trustlab-" . $slug . ".crt"; return $this->getLinuxHeader() . "header_info \"Installing CA: {$cert->common_name}\"\n" . "\n" . "check_root\n" . "\n" . "TEMP_CERT=\"/tmp/trustlab-{$cert->uuid}.crt\"\n" . "\n" . "msg_info \"Downloading certificate...\"\n" . "if curl -sL \"{$cdnUrl}\" -o \"\$TEMP_CERT\"; then\n" . " msg_ok \"Certificate downloaded.\"\n" . "else\n" . " msg_err \"Failed to download certificate from CDN.\"\n" . " exit 1\n" . "fi\n" . "\n" . "msg_info \"Detecting OS and checking ca-certificates package...\"\n" . "if [ -f /etc/debian_version ]; then\n" . " apt-get update -qq >/dev/null 2>&1 && apt-get install -y -qq ca-certificates >/dev/null 2>&1\n" . " mkdir -p /usr/local/share/ca-certificates\n" . " TARGET_DIR=\"/usr/local/share/ca-certificates\"\n" . " UPDATE_CMD=\"update-ca-certificates\"\n" . "elif [ -f /etc/redhat-release ]; then\n" . " yum install -y -q ca-certificates >/dev/null 2>&1 || dnf install -y -q ca-certificates >/dev/null 2>&1\n" . " mkdir -p /etc/pki/ca-trust/source/anchors\n" . " TARGET_DIR=\"/etc/pki/ca-trust/source/anchors\"\n" . " UPDATE_CMD=\"update-ca-trust extract\"\n" . "elif [ -f /etc/arch-release ]; then\n" . " pacman -Sy --noconfirm -q ca-certificates >/dev/null 2>&1\n" . " mkdir -p /etc/ca-certificates/trust-source/anchors\n" . " TARGET_DIR=\"/etc/ca-certificates/trust-source/anchors\"\n" . " UPDATE_CMD=\"trust extract-compat\"\n" . "else\n" . " msg_err \"Unsupported Linux distribution.\"\n" . " exit 1\n" . "fi\n" . "\n" . "msg_info \"Installing certificate to \$TARGET_DIR...\"\n" . "cp \"\$TEMP_CERT\" \"\$TARGET_DIR/{$filename}\"\n" . "\n" . "msg_info \"Updating certificate store...\"\n" . "if \$UPDATE_CMD >/dev/null 2>&1; then\n" . " msg_ok \"Store updated successfully.\"\n" . " curl -X POST -s \"" . config('app.url') . "/api/public/ca-certificates/{$cert->serial_number}/track\" >/dev/null 2>&1\n" . "else\n" . " msg_err \"Failed to update certificate store.\"\n" . " exit 1\n" . "fi\n" . "\n" . "rm \"\$TEMP_CERT\"\n" . "echo -e \"\n\${GN} Installation Complete! \${CL}\"\n" . "echo -e \"\${BL} Verify with: \${CL}ls \$TARGET_DIR/trustlab-*\"\n"; } /** * Common Linux Bash Header with Colors & Helpers */ private function getLinuxHeader(): string { return "#!/bin/bash\n" . "# TrustLab CA Installer\n" . "# Generated via CaInstallerService\n" . "\n" . "set -e\n" . "\n" . "YW=$(echo \"\\033[33m\")\n" . "BL=$(echo \"\\033[36m\")\n" . "RD=$(echo \"\\033[01;31m\")\n" . "BGN=$(echo \"\\033[4;32m\")\n" . "GN=$(echo \"\\033[1;92m\")\n" . "DGN=$(echo \"\\033[32m\")\n" . "CL=$(echo \"\\033[m\")\n" . "CM=\"\${GN}✓\${CL}\"\n" . "CROSS=\"\${RD}✗\${CL}\"\n" . "BFR=\"\\\\r\\\\033[K\"\n" . "HOLD=\"-\"\n" . "\n" . "header_info() {\n" . " clear\n" . " cat << \"EOF\"\n" . "\${BL}\n" . " _______ _____ _ _ _____ _______ _ _______ ______ \n" . " |__ __|| __ \| | | |/ ____||__ __|| | |__ __|| _ |\n" . " | | | |__) || | | || (___ | | | | | | | |_) |\n" . " | | | _ / | | | | \___ \ | | | | | | | _ < \n" . " | | | | \ \ | |__| | ____) | | | | |____ | | | |_) |\n" . " |_| |_| \_\| \____/ |_____/ |_| |______| |_| |______|\${CL}\n" . "\n" . "EOF\n" . "}\n" . "\n" . "msg_info() {\n" . " local msg=\"$1\"\n" . " echo -ne \" \${BL}[ INFO ]\${CL} \${msg}...\"\n" . "}\n" . "\n" . "msg_ok() {\n" . " local msg=\"$1\"\n" . " echo -e \"\${BFR} \${GN}[ OK ]\${CL} \${msg}\"\n" . "}\n" . "\n" . "msg_err() {\n" . " local msg=\"$1\"\n" . " echo -e \"\${BFR} \${RD}[ FAIL ]\${CL} \${msg}\"\n" . "}\n" . "\n" . "check_root() {\n" . " if [ \"$(id -u)\" -ne 0 ]; then\n" . " msg_err \"Please run as root (sudo).\"\n" . " exit 1\n" . " fi\n" . "}\n" . "\n"; } /** * Upload individual installers (SH, BAT, MAC) to CDN. */ public function uploadIndividualInstallersOnly(CaCertificate $cert, string $mode = 'both') { $slug = Str::slug($cert->common_name); $cacheControl = 'no-cache, no-store, must-revalidate'; $syncs = []; if ($mode === 'archive' || $mode === 'both') { $syncs[] = ['base' => "ca/archives/{$cert->uuid}/installers/trustlab-{$slug}", 'isArchive' => true]; } if ($mode === 'latest' || $mode === 'both') { $syncs[] = ['base' => "ca/installers/trustlab-{$slug}", 'isArchive' => false]; } foreach ($syncs as $sync) { $batPath = $sync['base'] . '.bat'; $macPath = $sync['base'] . '.mobileconfig'; $linuxPath = $sync['base'] . '.sh'; // 3. Generate and Upload Windows Installer (.bat) $batContent = $this->generateWindowsInstaller($cert, $sync['isArchive']); Storage::disk('r2-public')->put($batPath, $batContent, [ 'visibility' => 'public', 'ContentType' => 'text/plain', 'CacheControl' => $cacheControl ]); // 4. Generate and Upload macOS Profile (.mobileconfig) $macContent = $this->generateMacInstaller($cert); // macOS profiles are self-contained Storage::disk('r2-public')->put($macPath, $macContent, [ 'visibility' => 'public', 'ContentType' => 'application/x-apple-aspen-config', 'CacheControl' => $cacheControl ]); // 5. Generate and Upload Linux Script (.sh) $linuxContent = $this->generateLinuxInstaller($cert, $sync['isArchive']); Storage::disk('r2-public')->put($linuxPath, $linuxContent, [ 'visibility' => 'public', 'ContentType' => 'text/plain', 'CacheControl' => $cacheControl ]); } $cert->update([ 'bat_path' => "ca/installers/trustlab-{$slug}.bat", 'mac_path' => "ca/installers/trustlab-{$slug}.mobileconfig", 'linux_path' => "ca/installers/trustlab-{$slug}.sh", 'last_synced_at' => now() ]); return true; } /** * Generate Global Bundles (Installer Sapujagat) */ public function syncAllBundles() { $certificates = CaCertificate::all(); if ($certificates->isEmpty()) return false; $cacheControl = 'no-cache, no-store, must-revalidate'; // 1. Linux Bundle (.sh) // Note: Using the same Proxmox-style header $now = now()->format('Y-m-d H:i:s'); $shContent = $this->getLinuxHeader() . "header_info \"Bundle Installer (All CAs)\"\n" . "\n" . "check_root\n" . "\n" . "msg_info \"Detecting OS and checking ca-certificates package...\"\n" . "if [ -f /etc/debian_version ]; then\n" . " apt-get update -qq >/dev/null 2>&1 && apt-get install -y -qq ca-certificates >/dev/null 2>&1\n" . " mkdir -p /usr/local/share/ca-certificates\n" . " TARGET_DIR=\"/usr/local/share/ca-certificates\"\n" . " UPDATE_CMD=\"update-ca-certificates\"\n" . "elif [ -f /etc/redhat-release ]; then\n" . " yum install -y -q ca-certificates >/dev/null 2>&1 || dnf install -y -q ca-certificates >/dev/null 2>&1\n" . " mkdir -p /etc/pki/ca-trust/source/anchors\n" . " TARGET_DIR=\"/etc/pki/ca-trust/source/anchors\"\n" . " UPDATE_CMD=\"update-ca-trust extract\"\n" . "elif [ -f /etc/arch-release ]; then\n" . " pacman -Sy --noconfirm -q ca-certificates >/dev/null 2>&1\n" . " mkdir -p /etc/ca-certificates/trust-source/anchors\n" . " TARGET_DIR=\"/etc/ca-certificates/trust-source/anchors\"\n" . " UPDATE_CMD=\"trust extract-compat\"\n" . "else\n" . " msg_err \"Unsupported Linux distribution.\"\n" . " exit 1\n" . "fi\n" . "\n"; // Loop add certificate downloads to bundle foreach ($certificates as $cert) { $slug = Str::slug($cert->common_name); // Use public URL for public accessibility $cdnUrl = Storage::disk('r2-public')->url("ca/{$slug}.crt"); $filename = "trustlab-" . $slug . ".crt"; $shContent .= "msg_info \"Processing: {$cert->common_name}\"\n"; $shContent .= "curl -sL \"{$cdnUrl}\" -o \"\$TARGET_DIR/{$filename}\"\n"; // Telemetry Ping (Silent) $shContent .= "curl -X POST -s \"" . config('app.url') . "/api/public/ca-certificates/{$cert->serial_number}/track\" >/dev/null 2>&1\n"; } $shContent .= "\nmsg_info \"Updating certificate store...\"\n" . "if \$UPDATE_CMD >/dev/null 2>&1; then\n" . " msg_ok \"All certificates installed & store updated.\"\n" . "else\n" . " msg_err \"Failed to update certificate store.\"\n" . " exit 1\n" . "fi\n" . "\n" . "echo -e \"\n\${GN} Complete! Installed all trustlab certs.\${CL}\"\n"; Storage::disk('r2-public')->put('ca/bundles/trustlab-all.sh', $shContent, [ 'visibility' => 'public', 'ContentType' => 'text/plain', 'CacheControl' => $cacheControl ]); // 2. Windows Bundle (.bat) // Hybrid Batch + PowerShell script for rich UI $batContent = "@echo off\r\n" . "setlocal\r\n" . "title TrustLab All-in-One Installer\r\n" . "call :printHeader\r\n" . "\r\n" . "echo.\r\n" . "call :printInfo \"Starting Bundle Installation...\"\r\n" . "\r\n"; foreach ($certificates as $cert) { $slug = Str::slug($cert->common_name); $cdnUrl = Storage::disk('r2-public')->url("ca/{$slug}.crt"); $store = $cert->ca_type === 'root' ? 'Root' : 'CA'; $batContent .= "set \"TEMP_CERT=%TEMP%\\trustlab-{$slug}.crt\"\r\n" . "call :printAction \"Installing {$cert->common_name}...\"\r\n" . "powershell -Command \"Invoke-WebRequest -Uri '{$cdnUrl}' -OutFile '%TEMP_CERT%'\"\r\n" . "certutil -addstore -f \"{$store}\" \"%TEMP_CERT%\" >nul 2>&1\r\n" . "powershell -Command \"Invoke-WebRequest -Uri '" . config('app.url') . "/api/public/ca-certificates/{$cert->serial_number}/track' -Method POST -ErrorAction SilentlyContinue\" >nul 2>&1\r\n" . "del \"%TEMP_CERT%\"\r\n"; } $batContent .= "\r\n" . "call :printSuccess \"All certificates processed.\"\r\n" . "echo.\r\n" . "call :printInfo \"Press any key to close...\"\r\n" . "pause >nul\r\n" . "exit /b\r\n" . "\r\n" . ":printHeader\r\n" . "cls\r\n" . "powershell -Command \"Write-Host ' _______ _____ _ _ _____ _______ _ _______ ______ ' -ForegroundColor Cyan\"\r\n" . "powershell -Command \"Write-Host ' |__ __|| __ \| | | |/ ____||__ __|| | |__ __|| _ |' -ForegroundColor Cyan\"\r\n" . "powershell -Command \"Write-Host ' | | | |__) || | | || (___ | | | | | | | |_) |' -ForegroundColor Cyan\"\r\n" . "powershell -Command \"Write-Host ' | | | _ / | | | | \___ \ | | | | | | | _ < ' -ForegroundColor Cyan\"\r\n" . "powershell -Command \"Write-Host ' | | | | \ \ | |__| | ____) | | | | |____ | | | |_) |' -ForegroundColor Cyan\"\r\n" . "powershell -Command \"Write-Host ' |_| |_| \_\| \____/ |_____/ |_| |______| |_| |______|' -ForegroundColor Cyan\"\r\n" . "powershell -Command \"Write-Host ' '\"\r\n" . "exit /b\r\n" . "\r\n" . ":printInfo\r\n" . "powershell -Command \"Write-Host ' [ INFO ] %~1' -ForegroundColor Cyan\"\r\n" . "exit /b\r\n" . "\r\n" . ":printAction\r\n" . "powershell -Command \"Write-Host ' [ .... ] %~1' -ForegroundColor Yellow\"\r\n" . "exit /b\r\n" . "\r\n" . ":printSuccess\r\n" . "powershell -Command \"Write-Host ' [ OK ] %~1' -ForegroundColor Green\"\r\n" . "exit /b\r\n" . "\r\n" . ":printError\r\n" . "powershell -Command \"Write-Host ' [ FAIL ] %~1' -ForegroundColor Red\"\r\n" . "exit /b\r\n"; Storage::disk('r2-public')->put('ca/bundles/trustlab-all.bat', $batContent, [ 'visibility' => 'public', 'ContentType' => 'text/plain', 'CacheControl' => $cacheControl ]); // 3. MacOS Bundle (Config Profile - logic kept as is) $uuid1 = Str::uuid()->toString(); $payloadContent = ""; foreach ($certificates as $cert) { $certBase64 = base64_encode($cert->cert_content); $uuidSub = Str::uuid()->toString(); $payloadType = $cert->ca_type === 'root' ? 'com.apple.security.root' : 'com.apple.security.pkcs1'; $payloadContent .= " \n" . " PayloadCertificateFileName\n" . " {$cert->common_name}.crt\n" . " PayloadContent\n" . " {$certBase64}\n" . " PayloadDescription\n" . " TrustLab CA Certificate\n" . " PayloadDisplayName\n" . " {$cert->common_name}\n" . " PayloadIdentifier\n" . " com.trustlab.bundle.{$cert->uuid}\n" . " PayloadType\n" . " {$payloadType}\n" . " PayloadUUID\n" . " {$uuidSub}\n" . " PayloadVersion\n" . " 1\n" . " \n"; } $macContent = "\n" . "\n" . "\n" . "\n" . " PayloadContent\n" . " \n" . $payloadContent . " \n" . " PayloadDescription\n" . " TrustLab All-in-One CA Bundle\n" . " PayloadDisplayName\n" . " TrustLab CA Bundle\n" . " PayloadIdentifier\n" . " com.trustlab.ca.bundle\n" . " PayloadRemovalDisallowed\n" . " \n" . " PayloadType\n" . " Configuration\n" . " PayloadUUID\n" . " {$uuid1}\n" . " PayloadVersion\n" . " 1\n" . "\n" . ""; Storage::disk('r2-public')->delete('ca/bundles/trustlab-all.mobileconfig'); Storage::disk('r2-public')->put('ca/bundles/trustlab-all.mobileconfig', $macContent, [ 'visibility' => 'public', 'ContentType' => 'application/x-apple-aspen-config', 'CacheControl' => $cacheControl ]); return true; } }