mirror of
https://github.com/AikidoSec/safe-chain.git
synced 2026-05-26 12:10:49 +00:00
Use safeSpawn instead of execSync
This commit is contained in:
parent
9b61a325fa
commit
8b189443b7
1 changed files with 55 additions and 54 deletions
|
|
@ -1,8 +1,8 @@
|
||||||
import { arch, tmpdir } from "os";
|
import { arch, tmpdir } from "os";
|
||||||
import { unlinkSync } from "fs";
|
import { unlinkSync } from "fs";
|
||||||
import { join } from "path";
|
import { join } from "path";
|
||||||
import { execSync } from "child_process";
|
|
||||||
import { ui } from "../environment/userInteraction.js";
|
import { ui } from "../environment/userInteraction.js";
|
||||||
|
import { safeSpawn } from "../utils/safeSpawn.js";
|
||||||
import {
|
import {
|
||||||
getAgentDownloadUrl,
|
getAgentDownloadUrl,
|
||||||
getAgentVersion,
|
getAgentVersion,
|
||||||
|
|
@ -10,7 +10,7 @@ import {
|
||||||
} from "./downloadAgent.js";
|
} from "./downloadAgent.js";
|
||||||
|
|
||||||
export async function installOnWindows() {
|
export async function installOnWindows() {
|
||||||
if (!isRunningAsAdmin()) {
|
if (!(await isRunningAsAdmin())) {
|
||||||
ui.writeError("Administrator privileges required.");
|
ui.writeError("Administrator privileges required.");
|
||||||
ui.writeInformation(
|
ui.writeInformation(
|
||||||
"Please run this command in an elevated terminal (Run as Administrator).",
|
"Please run this command in an elevated terminal (Run as Administrator).",
|
||||||
|
|
@ -32,18 +32,18 @@ export async function installOnWindows() {
|
||||||
await downloadFile(downloadUrl, msiPath);
|
await downloadFile(downloadUrl, msiPath);
|
||||||
|
|
||||||
ui.emptyLine();
|
ui.emptyLine();
|
||||||
stopServiceIfRunning();
|
await stopServiceIfRunning();
|
||||||
uninstallIfInstalled();
|
await uninstallIfInstalled();
|
||||||
|
|
||||||
// Wait a moment for uninstall to complete
|
// Wait a moment for uninstall to complete
|
||||||
await new Promise((resolve) => setTimeout(resolve, 2000));
|
await new Promise((resolve) => setTimeout(resolve, 2000));
|
||||||
|
|
||||||
ui.writeInformation("⚙️ Installing SafeChain Agent...");
|
ui.writeInformation("⚙️ Installing SafeChain Agent...");
|
||||||
runMsiInstaller(msiPath);
|
await runMsiInstaller(msiPath);
|
||||||
|
|
||||||
ui.emptyLine();
|
ui.emptyLine();
|
||||||
ui.writeInformation("🚀 Starting SafeChain Agent service...");
|
ui.writeInformation("🚀 Starting SafeChain Agent service...");
|
||||||
startService();
|
await startService();
|
||||||
|
|
||||||
ui.writeVerbose(`Cleaning up temporary file: ${msiPath}`);
|
ui.writeVerbose(`Cleaning up temporary file: ${msiPath}`);
|
||||||
cleanup(msiPath);
|
cleanup(msiPath);
|
||||||
|
|
@ -53,13 +53,9 @@ export async function installOnWindows() {
|
||||||
ui.emptyLine();
|
ui.emptyLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
function isRunningAsAdmin() {
|
async function isRunningAsAdmin() {
|
||||||
try {
|
const result = await safeSpawn("net", ["session"], { stdio: "ignore" });
|
||||||
execSync("net session", { stdio: "ignore" });
|
return result.status === 0;
|
||||||
return true;
|
|
||||||
} catch {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getWindowsArchitecture() {
|
function getWindowsArchitecture() {
|
||||||
|
|
@ -69,70 +65,75 @@ function getWindowsArchitecture() {
|
||||||
throw new Error(`Unsupported architecture: ${nodeArch}`);
|
throw new Error(`Unsupported architecture: ${nodeArch}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
function uninstallIfInstalled() {
|
async function uninstallIfInstalled() {
|
||||||
try {
|
|
||||||
// Use PowerShell to find the product code, then use msiexec to uninstall
|
// Use PowerShell to find the product code, then use msiexec to uninstall
|
||||||
// This is the modern alternative to wmic which is deprecated
|
// This is the modern alternative to wmic which is deprecated
|
||||||
const findProductCodeCmd = `powershell -Command "$app = Get-WmiObject -Class Win32_Product -Filter \\"Name='SafeChain Agent'\\"; if ($app) { Write-Output $app.IdentifyingNumber }"`;
|
const powershellScript = `$app = Get-WmiObject -Class Win32_Product -Filter "Name='SafeChain Agent'"; if ($app) { Write-Output $app.IdentifyingNumber }`;
|
||||||
ui.writeVerbose(`Finding product code: ${findProductCodeCmd}`);
|
ui.writeVerbose(`Finding product code with PowerShell`);
|
||||||
|
|
||||||
const productCode = execSync(findProductCodeCmd, {
|
const result = await safeSpawn("powershell", ["-Command", powershellScript], {
|
||||||
encoding: "utf8",
|
stdio: "pipe",
|
||||||
}).trim();
|
});
|
||||||
|
|
||||||
|
if (result.status !== 0) {
|
||||||
|
ui.writeVerbose("No existing installation found (fresh install).");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const productCode = result.stdout.trim();
|
||||||
|
|
||||||
if (productCode) {
|
if (productCode) {
|
||||||
ui.writeInformation("🗑️ Removing previous installation...");
|
ui.writeInformation("🗑️ Removing previous installation...");
|
||||||
ui.writeVerbose(`Found product code: ${productCode}`);
|
ui.writeVerbose(`Found product code: ${productCode}`);
|
||||||
ui.writeVerbose(`Running: msiexec /x ${productCode} /qn /norestart`);
|
ui.writeVerbose(`Running: msiexec /x ${productCode} /qn /norestart`);
|
||||||
execSync(`msiexec /x ${productCode} /qn /norestart`, {
|
await safeSpawn("msiexec", ["/x", productCode, "/qn", "/norestart"], {
|
||||||
stdio: "inherit",
|
stdio: "inherit",
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
ui.writeVerbose("No existing installation found (fresh install).");
|
ui.writeVerbose("No existing installation found (fresh install).");
|
||||||
}
|
}
|
||||||
} catch {
|
|
||||||
// Not installed or uninstall failed, which is fine for a fresh install
|
|
||||||
ui.writeVerbose("No existing installation found (fresh install).");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} msiPath
|
* @param {string} msiPath
|
||||||
*/
|
*/
|
||||||
function runMsiInstaller(msiPath) {
|
async function runMsiInstaller(msiPath) {
|
||||||
// /i = install
|
// /i = install
|
||||||
// /qn = quiet mode (no UI)
|
// /qn = quiet mode (no UI)
|
||||||
ui.writeVerbose(`Running: msiexec /i "${msiPath}" /qn`);
|
ui.writeVerbose(`Running: msiexec /i "${msiPath}" /qn`);
|
||||||
execSync(`msiexec /i "${msiPath}" /qn`, { stdio: "inherit" }); // noopengrep this is ok, we control the msiPath
|
await safeSpawn("msiexec", ["/i", msiPath, "/qn"], { stdio: "inherit" });
|
||||||
}
|
}
|
||||||
|
|
||||||
function stopServiceIfRunning() {
|
async function stopServiceIfRunning() {
|
||||||
try {
|
|
||||||
ui.writeInformation("⏹️ Stopping running service...");
|
ui.writeInformation("⏹️ Stopping running service...");
|
||||||
ui.writeVerbose('Running: net stop "SafeChainAgent"');
|
ui.writeVerbose('Running: net stop "SafeChainAgent"');
|
||||||
execSync('net stop "SafeChainAgent"', { stdio: "inherit" });
|
const result = await safeSpawn("net", ["stop", "SafeChainAgent"], {
|
||||||
} catch {
|
stdio: "inherit",
|
||||||
// Service is not running or doesn't exist, which is fine
|
});
|
||||||
|
|
||||||
|
if (result.status !== 0) {
|
||||||
ui.writeVerbose("Service not running (will start after installation).");
|
ui.writeVerbose("Service not running (will start after installation).");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function startService() {
|
async function startService() {
|
||||||
try {
|
|
||||||
// Check if service is already running
|
// Check if service is already running
|
||||||
ui.writeVerbose('Checking service status: sc query "SafeChainAgent"');
|
ui.writeVerbose('Checking service status: sc query "SafeChainAgent"');
|
||||||
const status = execSync('sc query "SafeChainAgent"', { encoding: "utf8" });
|
const queryResult = await safeSpawn("sc", ["query", "SafeChainAgent"], {
|
||||||
|
stdio: "pipe",
|
||||||
|
});
|
||||||
|
|
||||||
if (status.includes("RUNNING")) {
|
if (queryResult.status === 0 && queryResult.stdout.includes("RUNNING")) {
|
||||||
ui.writeVerbose("SafeChain Agent service is already running.");
|
ui.writeVerbose("SafeChain Agent service is already running.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} catch {
|
|
||||||
|
if (queryResult.status !== 0) {
|
||||||
ui.writeVerbose("Service not found or query failed, attempting to start.");
|
ui.writeVerbose("Service not found or query failed, attempting to start.");
|
||||||
}
|
}
|
||||||
|
|
||||||
ui.writeVerbose('Running: net start "SafeChainAgent"');
|
ui.writeVerbose('Running: net start "SafeChainAgent"');
|
||||||
execSync('net start "SafeChainAgent"', { stdio: "inherit" });
|
await safeSpawn("net", ["start", "SafeChainAgent"], { stdio: "inherit" });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue