mirror of
https://github.com/AikidoSec/safe-chain.git
synced 2026-05-26 12:10:49 +00:00
Add ultimate installer for Windows
This commit is contained in:
parent
f358709ab2
commit
879b37e164
2 changed files with 121 additions and 12 deletions
|
|
@ -16,6 +16,7 @@ import path from "path";
|
||||||
import { fileURLToPath } from "url";
|
import { fileURLToPath } from "url";
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import { knownAikidoTools } from "../src/shell-integration/helpers.js";
|
import { knownAikidoTools } from "../src/shell-integration/helpers.js";
|
||||||
|
import { installUltimate } from "../src/installation/installUltimate.js";
|
||||||
|
|
||||||
/** @type {string} */
|
/** @type {string} */
|
||||||
// This checks the current file's dirname in a way that's compatible with:
|
// This checks the current file's dirname in a way that's compatible with:
|
||||||
|
|
@ -62,6 +63,8 @@ if (tool) {
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
} else if (command === "setup") {
|
} else if (command === "setup") {
|
||||||
setup();
|
setup();
|
||||||
|
} else if (command === "--ultimate") {
|
||||||
|
installUltimate();
|
||||||
} else if (command === "teardown") {
|
} else if (command === "teardown") {
|
||||||
teardownDirectories();
|
teardownDirectories();
|
||||||
teardown();
|
teardown();
|
||||||
|
|
@ -82,36 +85,41 @@ if (tool) {
|
||||||
|
|
||||||
function writeHelp() {
|
function writeHelp() {
|
||||||
ui.writeInformation(
|
ui.writeInformation(
|
||||||
chalk.bold("Usage: ") + chalk.cyan("safe-chain <command>")
|
chalk.bold("Usage: ") + chalk.cyan("safe-chain <command>"),
|
||||||
);
|
);
|
||||||
ui.emptyLine();
|
ui.emptyLine();
|
||||||
ui.writeInformation(
|
ui.writeInformation(
|
||||||
`Available commands: ${chalk.cyan("setup")}, ${chalk.cyan(
|
`Available commands: ${chalk.cyan("setup")}, ${chalk.cyan(
|
||||||
"teardown"
|
"teardown",
|
||||||
)}, ${chalk.cyan("setup-ci")}, ${chalk.cyan("help")}, ${chalk.cyan(
|
)}, ${chalk.cyan("setup-ci")}, ${chalk.cyan("help")}, ${chalk.cyan(
|
||||||
"--version"
|
"--version",
|
||||||
)}`
|
)}`,
|
||||||
);
|
);
|
||||||
ui.emptyLine();
|
ui.emptyLine();
|
||||||
ui.writeInformation(
|
ui.writeInformation(
|
||||||
`- ${chalk.cyan(
|
`- ${chalk.cyan(
|
||||||
"safe-chain setup"
|
"safe-chain setup",
|
||||||
)}: This will setup your shell to wrap safe-chain around npm, npx, yarn, pnpm, pnpx, bun, bunx, pip and pip3.`
|
)}: This will setup your shell to wrap safe-chain around npm, npx, yarn, pnpm, pnpx, bun, bunx, pip and pip3.`,
|
||||||
);
|
);
|
||||||
ui.writeInformation(
|
ui.writeInformation(
|
||||||
`- ${chalk.cyan(
|
`- ${chalk.cyan(
|
||||||
"safe-chain teardown"
|
"safe-chain --ultimate",
|
||||||
)}: This will remove safe-chain aliases from your shell configuration.`
|
)}: This installs the ultimate version of safe-chain, enabling protection for more eco-systems (vscode).`,
|
||||||
);
|
);
|
||||||
ui.writeInformation(
|
ui.writeInformation(
|
||||||
`- ${chalk.cyan(
|
`- ${chalk.cyan(
|
||||||
"safe-chain setup-ci"
|
"safe-chain teardown",
|
||||||
)}: This will setup safe-chain for CI environments by creating shims and modifying the PATH.`
|
)}: This will remove safe-chain aliases from your shell configuration.`,
|
||||||
|
);
|
||||||
|
ui.writeInformation(
|
||||||
|
`- ${chalk.cyan(
|
||||||
|
"safe-chain setup-ci",
|
||||||
|
)}: This will setup safe-chain for CI environments by creating shims and modifying the PATH.`,
|
||||||
);
|
);
|
||||||
ui.writeInformation(
|
ui.writeInformation(
|
||||||
`- ${chalk.cyan("safe-chain --version")} (or ${chalk.cyan(
|
`- ${chalk.cyan("safe-chain --version")} (or ${chalk.cyan(
|
||||||
"-v"
|
"-v",
|
||||||
)}): Display the current version of safe-chain.`
|
)}): Display the current version of safe-chain.`,
|
||||||
);
|
);
|
||||||
ui.emptyLine();
|
ui.emptyLine();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
101
packages/safe-chain/src/installation/installUltimate.js
Normal file
101
packages/safe-chain/src/installation/installUltimate.js
Normal file
|
|
@ -0,0 +1,101 @@
|
||||||
|
import { platform, arch, tmpdir } from "os";
|
||||||
|
import { createWriteStream, unlinkSync } from "fs";
|
||||||
|
import { join } from "path";
|
||||||
|
import { execSync } from "child_process";
|
||||||
|
import { pipeline } from "stream/promises";
|
||||||
|
import fetch from "make-fetch-happen";
|
||||||
|
import { ui } from "../environment/userInteraction.js";
|
||||||
|
|
||||||
|
const ULTIMATE_VERSION = "v0.2.0";
|
||||||
|
|
||||||
|
export function installUltimate() {
|
||||||
|
const operatingSystem = platform();
|
||||||
|
|
||||||
|
if (operatingSystem === "win32") {
|
||||||
|
installOnWindows();
|
||||||
|
} else {
|
||||||
|
ui.writeInformation(
|
||||||
|
`${operatingSystem} is not supported yet by safe-chain's ultimate version.`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function installOnWindows() {
|
||||||
|
if (!isRunningAsAdmin()) {
|
||||||
|
ui.writeError("Administrator privileges required.");
|
||||||
|
ui.writeInformation(
|
||||||
|
"Please run this command in an elevated terminal (Run as Administrator)."
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const architecture = getWindowsArchitecture();
|
||||||
|
const downloadUrl = buildDownloadUrl(architecture);
|
||||||
|
const msiPath = join(tmpdir(), `SafeChainAgent-${Date.now()}.msi`);
|
||||||
|
|
||||||
|
ui.writeInformation(`Downloading SafeChain Agent ${ULTIMATE_VERSION} for ${architecture}...`);
|
||||||
|
ui.writeVerbose(`Download URL: ${downloadUrl}`);
|
||||||
|
ui.writeVerbose(`Destination: ${msiPath}`);
|
||||||
|
await downloadFile(downloadUrl, msiPath);
|
||||||
|
|
||||||
|
ui.writeInformation("Installing SafeChain Agent...");
|
||||||
|
ui.writeVerbose(`Running: msiexec /i "${msiPath}" /qn`);
|
||||||
|
runMsiInstaller(msiPath);
|
||||||
|
|
||||||
|
ui.writeVerbose(`Cleaning up temporary file: ${msiPath}`);
|
||||||
|
cleanup(msiPath);
|
||||||
|
ui.writeInformation("SafeChain Agent installed successfully!");
|
||||||
|
}
|
||||||
|
|
||||||
|
function isRunningAsAdmin() {
|
||||||
|
try {
|
||||||
|
execSync("net session", { stdio: "ignore" });
|
||||||
|
return true;
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getWindowsArchitecture() {
|
||||||
|
const nodeArch = arch();
|
||||||
|
if (nodeArch === "x64") return "amd64";
|
||||||
|
if (nodeArch === "arm64") return "arm64";
|
||||||
|
throw new Error(`Unsupported architecture: ${nodeArch}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} architecture
|
||||||
|
*/
|
||||||
|
function buildDownloadUrl(architecture) {
|
||||||
|
return `https://github.com/AikidoSec/safechain-internals/releases/download/${ULTIMATE_VERSION}/SafeChainAgent-windows-${architecture}.msi`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} url
|
||||||
|
* @param {string} destPath
|
||||||
|
*/
|
||||||
|
async function downloadFile(url, destPath) {
|
||||||
|
const response = await fetch(url);
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`Download failed: ${response.statusText}`);
|
||||||
|
}
|
||||||
|
await pipeline(response.body, createWriteStream(destPath));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} msiPath
|
||||||
|
*/
|
||||||
|
function runMsiInstaller(msiPath) {
|
||||||
|
execSync(`msiexec /i "${msiPath}" /qn`, { stdio: "inherit" });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} msiPath
|
||||||
|
*/
|
||||||
|
function cleanup(msiPath) {
|
||||||
|
try {
|
||||||
|
unlinkSync(msiPath);
|
||||||
|
} catch {
|
||||||
|
// Ignore cleanup errors
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue