Add installer build scripts and configuration

This commit is contained in:
Reinier Criel 2025-11-25 08:21:35 -08:00
parent fb3a8582a2
commit 3420290ea9
22 changed files with 1377 additions and 7 deletions

View file

@ -0,0 +1,372 @@
#!/usr/bin/env node
/**
* System Proxy Configuration Manager for macOS
* node configure-proxy.js --install # Configure system proxy
* node configure-proxy.js --uninstall # Restore original settings
* node configure-proxy.js --status # Check current configuration
*/
import { execSync } from "child_process";
import * as fs from "fs";
import * as path from "path";
import { PROXY_HOST, AGENT_PORT as PROXY_PORT, CONFIG_FILE, BYPASS_DOMAINS } from "./settings.js";
/**
* Sanitize service name to prevent command injection
* Network service names from networksetup are trusted, but we sanitize as best practice
*/
function sanitizeServiceName(service) {
// Remove any characters that could be used for command injection
return service.replace(/[;&|`$()]/g, "");
}
/**
* Get all network services on the system
*/
function getNetworkServices() {
try {
const output = execSync("networksetup -listallnetworkservices", {
encoding: "utf-8",
});
// Parse output, skip first line (header) and disabled services (marked with *)
return output
.split("\n")
.slice(1)
.filter((line) => line.trim() && !line.startsWith("*"))
.map((line) => line.trim());
} catch (error) {
console.error("Failed to get network services:", error.message);
return [];
}
}
/**
* Get current proxy settings for a network service
*/
function getCurrentProxySettings(service) {
try {
const httpProxy = execSync(`networksetup -getwebproxy "${service}"`, {
encoding: "utf-8",
});
const httpsProxy = execSync(`networksetup -getsecurewebproxy "${service}"`, {
encoding: "utf-8",
});
const parseProxyOutput = (output) => {
const enabled = output.includes("Enabled: Yes");
const serverMatch = output.match(/Server: (.+)/);
const portMatch = output.match(/Port: (\d+)/);
return {
enabled,
server: serverMatch ? serverMatch[1].trim() : "",
port: portMatch ? parseInt(portMatch[1]) : 0,
};
};
return {
http: parseProxyOutput(httpProxy),
https: parseProxyOutput(httpsProxy),
};
} catch (error) {
console.error(`Failed to get proxy settings for ${service}:`, error.message);
return null;
}
}
/**
* Save current proxy settings to restore later
*/
function saveOriginalSettings(services) {
const settings = {};
for (const service of services) {
const current = getCurrentProxySettings(service);
if (current) {
settings[service] = current;
}
}
// Ensure directory exists
const configDir = path.dirname(CONFIG_FILE);
if (!fs.existsSync(configDir)) {
fs.mkdirSync(configDir, { recursive: true });
}
fs.writeFileSync(CONFIG_FILE, JSON.stringify(settings, null, 2));
console.log(`Saved original proxy settings to ${CONFIG_FILE}`);
}
/**
* Load saved proxy settings
*/
function loadOriginalSettings() {
if (!fs.existsSync(CONFIG_FILE)) {
console.warn("No saved settings found");
return null;
}
try {
const data = fs.readFileSync(CONFIG_FILE, "utf-8");
return JSON.parse(data);
} catch (error) {
console.error("Failed to load saved settings:", error.message);
return null;
}
}
/**
* Configure proxy for a network service
*/
function configureProxyForService(service) {
try {
console.log(`Configuring proxy for: ${service}`);
// Set HTTP proxy
execSync(
`networksetup -setwebproxy "${service}" ${PROXY_HOST} ${PROXY_PORT}`,
{ stdio: "ignore" }
);
// Set HTTPS proxy
execSync(
`networksetup -setsecurewebproxy "${service}" ${PROXY_HOST} ${PROXY_PORT}`,
{ stdio: "ignore" }
);
// Set bypass domains
const bypassDomainsStr = BYPASS_DOMAINS.join('" "');
execSync(
`networksetup -setproxybypassdomains "${service}" "${bypassDomainsStr}"`,
{ stdio: "ignore" }
);
// Enable proxies
execSync(`networksetup -setwebproxystate "${service}" on`, {
stdio: "ignore",
});
execSync(`networksetup -setsecurewebproxystate "${service}" on`, {
stdio: "ignore",
});
console.log(` Configured: ${service}`);
return true;
} catch (error) {
console.error(` Failed to configure ${service}:`, error.message);
return false;
}
}
/**
* Restore original proxy settings for a service
*/
function restoreProxyForService(service, settings) {
try {
console.log(`Restoring proxy for: ${service}`);
// Restore HTTP proxy
if (settings.http.enabled && settings.http.server) {
execSync(
`networksetup -setwebproxy "${service}" ${settings.http.server} ${settings.http.port}`,
{ stdio: "ignore" }
);
execSync(`networksetup -setwebproxystate "${service}" on`, {
stdio: "ignore",
});
} else {
execSync(`networksetup -setwebproxystate "${service}" off`, {
stdio: "ignore",
});
}
// Restore HTTPS proxy
if (settings.https.enabled && settings.https.server) {
execSync(
`networksetup -setsecurewebproxy "${service}" ${settings.https.server} ${settings.https.port}`,
{ stdio: "ignore" }
);
execSync(`networksetup -setsecurewebproxystate "${service}" on`, {
stdio: "ignore",
});
} else {
execSync(`networksetup -setsecurewebproxystate "${service}" off`, {
stdio: "ignore",
});
}
console.log(` Restored: ${service}`);
return true;
} catch (error) {
console.error(` Failed to restore ${service}:`, error.message);
return false;
}
}
/**
* Install: Configure system proxy
*/
function install() {
console.log("🔧 Configuring system proxy for Aikido Safe Chain...\n");
const services = getNetworkServices();
if (services.length === 0) {
console.error("No network services found");
process.exit(1);
}
console.log(`Found ${services.length} network service(s):\n - ${services.join("\n - ")}\n`);
// Save original settings
saveOriginalSettings(services);
// Configure each service
let successCount = 0;
for (const service of services) {
if (configureProxyForService(service)) {
successCount++;
}
}
console.log(`\nConfigured proxy for ${successCount}/${services.length} network services`);
console.log(`\nProxy settings:`);
console.log(` HTTP Proxy: ${PROXY_HOST}:${PROXY_PORT}`);
console.log(` HTTPS Proxy: ${PROXY_HOST}:${PROXY_PORT}`);
console.log(` Bypass: ${BYPASS_DOMAINS.join(", ")}`);
}
/**
* Uninstall: Restore original proxy settings
*/
function uninstall() {
console.log("Restoring original proxy settings...\n");
const savedSettings = loadOriginalSettings();
if (!savedSettings) {
console.log("No saved settings found. Disabling proxies...");
// Just disable proxies for all services
const services = getNetworkServices();
for (const service of services) {
try {
execSync(`networksetup -setwebproxystate "${service}" off`, {
stdio: "ignore",
});
execSync(`networksetup -setsecurewebproxystate "${service}" off`, {
stdio: "ignore",
});
console.log(`Disabled proxy for: ${service}`);
} catch (error) {
console.error(`Failed to disable proxy for ${service}`);
}
}
} else {
// Restore saved settings
let successCount = 0;
const serviceNames = Object.keys(savedSettings);
for (const service of serviceNames) {
if (restoreProxyForService(service, savedSettings[service])) {
successCount++;
}
}
// Remove config file
try {
fs.unlinkSync(CONFIG_FILE);
console.log(`Removed configuration file`);
} catch (error) {
console.warn(`Failed to remove config file: ${error.message}`);
}
}
}
/**
* Status: Show current proxy configuration
*/
function status() {
const services = getNetworkServices();
for (const service of services) {
console.log(`${service}:`);
const settings = getCurrentProxySettings(service);
if (settings) {
console.log(` HTTP: ${settings.http.enabled ? "OK" : "NOK"} ${settings.http.server || "None"}:${settings.http.port || 0}`);
console.log(` HTTPS: ${settings.https.enabled ? "OK" : "NOK"} ${settings.https.server || "None"}:${settings.https.port || 0}`);
} else {
console.log("Failed to get settings");
}
console.log();
}
// Check if Aikido proxy is configured
const aikidoConfigured = services.some((service) => {
const settings = getCurrentProxySettings(service);
return (
settings &&
((settings.http.enabled &&
settings.http.server === PROXY_HOST &&
settings.http.port === PROXY_PORT) ||
(settings.https.enabled &&
settings.https.server === PROXY_HOST &&
settings.https.port === PROXY_PORT))
);
});
if (aikidoConfigured) {
console.log("Aikido Safe Chain proxy is configured");
} else {
console.log("Aikido Safe Chain proxy is NOT configured");
}
// Check if saved settings exist
if (fs.existsSync(CONFIG_FILE)) {
console.log(`Original settings saved at: ${CONFIG_FILE}`);
} else {
console.log(`No saved settings found`);
}
}
/**
* Main
*/
function main() {
const args = process.argv.slice(2);
const command = args[0];
if (!command || command === "--help" || command === "-h") {
console.log("Aikido Safe Chain - Proxy Configuration Manager");
console.log("\nUsage:");
console.log(" node configure-proxy.js --install # Configure system proxy");
console.log(" node configure-proxy.js --uninstall # Restore original settings");
console.log(" node configure-proxy.js --status # Show current configuration");
process.exit(0);
}
switch (command) {
case "--install":
case "install":
install();
break;
case "--uninstall":
case "uninstall":
uninstall();
break;
case "--status":
case "status":
status();
break;
default:
console.error(`Unknown command: ${command}`);
console.log('Run with --help for usage information');
process.exit(1);
}
}
main();