mirror of
https://github.com/AikidoSec/safe-chain.git
synced 2026-05-26 12:10:49 +00:00
Skeleton
This commit is contained in:
parent
76acf43128
commit
e04c4b6f21
7 changed files with 92 additions and 19 deletions
|
|
@ -39,3 +39,7 @@ export function setEcoSystem(setting) {
|
|||
export const LOGGING_SILENT = "silent";
|
||||
export const LOGGING_NORMAL = "normal";
|
||||
export const LOGGING_VERBOSE = "verbose";
|
||||
|
||||
// OS trust store paths
|
||||
export const DARWIN_CA_PATH = "/Library/Keychains/System.keychain";
|
||||
export const LINUX_CA_PATH = "/usr/local/share/ca-certificates/safe-chain-ca.crt";
|
||||
|
|
|
|||
|
|
@ -1,7 +1,11 @@
|
|||
import { ui } from "../../environment/userInteraction.js";
|
||||
import { safeSpawn } from "../../utils/safeSpawn.js";
|
||||
import { mergeSafeChainProxyEnvironmentVariables } from "../../registryProxy/registryProxy.js";
|
||||
import { getCombinedCaBundlePath } from "../../registryProxy/certBundle.js";
|
||||
import { installSafeChainCA } from "../../registryProxy/certUtils.js";
|
||||
|
||||
function shouldMockCAInstall() {
|
||||
return process.env.SAFE_CHAIN_TEST_SKIP_CA_INSTALL === "1";
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} command
|
||||
|
|
@ -11,15 +15,11 @@ import { getCombinedCaBundlePath } from "../../registryProxy/certBundle.js";
|
|||
*/
|
||||
export async function runPip(command, args) {
|
||||
try {
|
||||
// Install Safe Chain CA in OS trust store before running pip, unless in test mode
|
||||
if (!shouldMockCAInstall()) {
|
||||
await installSafeChainCA();
|
||||
}
|
||||
const env = mergeSafeChainProxyEnvironmentVariables(process.env);
|
||||
|
||||
// Always provide Python with a complete CA bundle (Safe Chain CA + Mozilla + Node built-in roots)
|
||||
// so that any network request made by pip, including those outside explicit CLI args,
|
||||
// validates correctly under both MITM'd and tunneled HTTPS.
|
||||
const combinedCaPath = getCombinedCaBundlePath();
|
||||
env.REQUESTS_CA_BUNDLE = combinedCaPath;
|
||||
env.SSL_CERT_FILE = combinedCaPath;
|
||||
|
||||
const result = await safeSpawn(command, args, {
|
||||
stdio: "inherit",
|
||||
env,
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@ import forge from "node-forge";
|
|||
import path from "path";
|
||||
import fs from "fs";
|
||||
import os from "os";
|
||||
import { safeSpawn } from "../utils/safeSpawn.js";
|
||||
import { DARWIN_CA_PATH, LINUX_CA_PATH } from "../config/settings.js";
|
||||
|
||||
const certFolder = path.join(os.homedir(), ".safe-chain", "certs");
|
||||
const ca = loadCa();
|
||||
|
|
@ -116,3 +118,69 @@ function generateCa() {
|
|||
certificate: cert,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the Safe Chain CA certificate is already installed in the OS trust store.
|
||||
* @returns {Promise<boolean>}
|
||||
*/
|
||||
export async function isSafeChainCAInstalled() {
|
||||
const platform = os.platform();
|
||||
try {
|
||||
if (platform === "darwin") {
|
||||
// macOS: check System Keychain for cert
|
||||
const res = await safeSpawn("security", ["find-certificate", "-c", "safe-chain proxy", DARWIN_CA_PATH], { stdio: "pipe" });
|
||||
return res.stdout.includes("safe-chain proxy");
|
||||
} else if (platform === "linux") {
|
||||
// Linux: check for CA file
|
||||
return fs.existsSync(LINUX_CA_PATH);
|
||||
} else if (platform === "win32") {
|
||||
// Windows: check Root store for cert
|
||||
return await safeSpawn("certutil", ["-store", "Root", "safe-chain proxy"], { stdio: "pipe" }).then(res => res.stdout.includes("safe-chain proxy"));
|
||||
}
|
||||
} catch (err) {
|
||||
// If check fails, assume not installed
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Installs the Safe Chain CA certificate in the OS trust store.
|
||||
* Uses platform-specific commands. Optionally uses npm packages if available.
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
export async function installSafeChainCA() {
|
||||
const caPath = getCaCertPath();
|
||||
const platform = os.platform();
|
||||
try {
|
||||
const alreadyInstalled = await isSafeChainCAInstalled();
|
||||
if (alreadyInstalled) {
|
||||
console.log("Safe Chain CA already installed in OS trust store.");
|
||||
return;
|
||||
}
|
||||
if (platform === "darwin") {
|
||||
// macOS: use security CLI
|
||||
await safeSpawn("sudo", [
|
||||
"security",
|
||||
"add-trusted-cert",
|
||||
"-d",
|
||||
"-r", "trustRoot",
|
||||
"-k", DARWIN_CA_PATH,
|
||||
caPath
|
||||
], { stdio: "inherit" });
|
||||
} else if (platform === "linux") {
|
||||
// Linux: use update-ca-certificates
|
||||
await safeSpawn("sudo", ["cp", caPath, LINUX_CA_PATH], { stdio: "inherit" });
|
||||
await safeSpawn("sudo", ["update-ca-certificates"], { stdio: "inherit" });
|
||||
} else if (platform === "win32") {
|
||||
// Windows: use certutil
|
||||
await safeSpawn("certutil", ["-addstore", "-f", "Root", caPath], { stdio: "inherit" });
|
||||
} else {
|
||||
throw new Error("Unsupported OS for automatic CA installation. Please install manually.");
|
||||
}
|
||||
console.log("Safe Chain CA installed in OS trust store.");
|
||||
} catch (/** @type any */ error) {
|
||||
console.error("Failed to install Safe Chain CA:", error.message);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue