mirror of
https://github.com/AikidoSec/safe-chain.git
synced 2026-05-26 20:20:49 +00:00
Add installer changes
This commit is contained in:
parent
e765ccf303
commit
2158478894
13 changed files with 674 additions and 21 deletions
60
packages/safe-chain/src/agent/generateCert.js
Normal file
60
packages/safe-chain/src/agent/generateCert.js
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
/**
|
||||
* Generate certificate command for Safe Chain
|
||||
* Creates CA certificate and key for MITM proxy
|
||||
*/
|
||||
|
||||
import { generateCACertificate } from "../registryProxy/certUtils.js";
|
||||
import { writeFileSync, mkdirSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
import { homedir } from "node:os";
|
||||
import { ui } from "../environment/userInteraction.js";
|
||||
import chalk from "chalk";
|
||||
|
||||
/**
|
||||
* Generate certificate command
|
||||
* @param {string[]} args - Command line arguments
|
||||
*/
|
||||
export async function generateCertCommand(args) {
|
||||
// Parse output directory from --output flag
|
||||
let outputDir = join(homedir(), ".safe-chain");
|
||||
|
||||
for (let i = 0; i < args.length; i++) {
|
||||
if (args[i] === "--output" && args[i + 1]) {
|
||||
outputDir = args[i + 1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
ui.writeInformation(chalk.bold("Generating Safe Chain CA certificate..."));
|
||||
ui.emptyLine();
|
||||
|
||||
// Create output directory
|
||||
mkdirSync(outputDir, { recursive: true });
|
||||
|
||||
// Generate certificate
|
||||
const { cert, key } = generateCACertificate();
|
||||
|
||||
// Write certificate and key files
|
||||
const certPath = join(outputDir, "ca-cert.pem");
|
||||
const keyPath = join(outputDir, "ca-key.pem");
|
||||
|
||||
writeFileSync(certPath, cert);
|
||||
writeFileSync(keyPath, key);
|
||||
|
||||
ui.writeInformation(chalk.green("✓") + " Certificate generated successfully!");
|
||||
ui.emptyLine();
|
||||
ui.writeInformation(chalk.bold("Files created:"));
|
||||
ui.writeInformation(` Certificate: ${chalk.cyan(certPath)}`);
|
||||
ui.writeInformation(` Private Key: ${chalk.cyan(keyPath)}`);
|
||||
ui.emptyLine();
|
||||
ui.writeInformation(chalk.dim("To install this certificate in your system trust store:"));
|
||||
ui.writeInformation(chalk.dim(" macOS: sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain " + certPath));
|
||||
ui.writeInformation(chalk.dim(" Linux: sudo cp " + certPath + " /usr/local/share/ca-certificates/ && sudo update-ca-certificates"));
|
||||
ui.writeInformation(chalk.dim(" Windows: certutil -addstore -f ROOT " + certPath));
|
||||
ui.emptyLine();
|
||||
} catch (/** @type {any} */ error) {
|
||||
ui.writeError(`Failed to generate certificate: ${error.message}`);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
|
@ -4,8 +4,6 @@ import chalk from "chalk";
|
|||
import { initializeCliArguments } from "../config/cliArguments.js";
|
||||
import { writeProxyState, clearProxyState } from "./proxyState.js";
|
||||
import { getCaCertPath } from "../registryProxy/certUtils.js";
|
||||
import { setup } from "../shell-integration/setup.js";
|
||||
import { teardown } from "../shell-integration/teardown.js";
|
||||
|
||||
/**
|
||||
* Run the Safe Chain proxy as a standalone service
|
||||
|
|
@ -26,9 +24,9 @@ export async function runCommand(args) {
|
|||
// Initialize logging from args
|
||||
initializeCliArguments(processedArgs);
|
||||
|
||||
// Automatically set up shell integration
|
||||
await setup();
|
||||
ui.emptyLine();
|
||||
// Note: We no longer call setup() here because the installer sets up
|
||||
// system-wide proxy environment variables via LaunchAgent on macOS
|
||||
// or systemd on Linux. The certificate is also installed at install time.
|
||||
|
||||
const service = new StandaloneProxyService({
|
||||
autoVerify: false
|
||||
|
|
@ -54,11 +52,14 @@ export async function runCommand(args) {
|
|||
ui.writeInformation(` PID: ${chalk.cyan(process.pid)}`);
|
||||
ui.emptyLine();
|
||||
|
||||
ui.writeInformation(chalk.bold("How to Use:"));
|
||||
ui.writeInformation(chalk.dim(" Restart your terminal, then run package managers normally:"));
|
||||
ui.writeInformation(chalk.cyan(" npm install <package>"));
|
||||
ui.writeInformation(chalk.cyan(" yarn add <package>"));
|
||||
ui.writeInformation(chalk.cyan(" pip3 install <package>"));
|
||||
ui.writeInformation(chalk.bold("Environment Variables Set:"));
|
||||
ui.writeInformation(` ${chalk.cyan("HTTPS_PROXY")}: http://localhost:${port}`);
|
||||
ui.writeInformation(` ${chalk.cyan("GLOBAL_AGENT_HTTP_PROXY")}: http://localhost:${port}`);
|
||||
ui.writeInformation(` ${chalk.cyan("NODE_EXTRA_CA_CERTS")}: ${getCaCertPath()}`);
|
||||
ui.emptyLine();
|
||||
|
||||
ui.writeInformation(chalk.bold("Package managers will use the proxy automatically."));
|
||||
ui.writeInformation(chalk.dim(" No shell wrappers or aliases needed."));
|
||||
ui.emptyLine();
|
||||
|
||||
ui.writeInformation(
|
||||
|
|
@ -104,9 +105,8 @@ export async function runCommand(args) {
|
|||
try {
|
||||
await service.stop();
|
||||
|
||||
// Remove shell integration
|
||||
ui.emptyLine();
|
||||
await teardown();
|
||||
// Note: We no longer call teardown() here because the environment
|
||||
// variables are managed by the system service (LaunchAgent/systemd)
|
||||
|
||||
process.exit(0);
|
||||
} catch (/** @type {any} */ error) {
|
||||
|
|
|
|||
|
|
@ -116,3 +116,15 @@ function generateCa() {
|
|||
certificate: cert,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate CA certificate and return as PEM strings
|
||||
* @returns {{cert: string, key: string}}
|
||||
*/
|
||||
export function generateCACertificate() {
|
||||
const { privateKey, certificate } = generateCa();
|
||||
return {
|
||||
cert: forge.pki.certificateToPem(certificate),
|
||||
key: forge.pki.privateKeyToPem(privateKey),
|
||||
};
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue