diff --git a/packages/safe-chain/src/registryProxy/ramaProxy/createAikidoEndpointConfigFile.js b/packages/safe-chain/src/registryProxy/ramaProxy/createAikidoEndpointConfigFile.js new file mode 100644 index 00000000..2eca1482 --- /dev/null +++ b/packages/safe-chain/src/registryProxy/ramaProxy/createAikidoEndpointConfigFile.js @@ -0,0 +1,93 @@ +import { writeFile } from "fs"; +import { join } from "path/posix"; +import { promisify } from "util"; +import { + getMinimumPackageAgeHours, + skipMinimumPackageAge, +} from "../../config/settings.js"; + +/** + * + * @param {string} dataFolder + * @returns string + */ +export async function createAikidoEndpointConfigFile(dataFolder) { + const configPath = join(dataFolder, "safe-chain-config.json"); + + const config = getConfigContent(); + const configJson = JSON.stringify(config); + + await promisify(writeFile)(configPath, configJson); + + return configPath; +} + +function getConfigContent() { + let cutoff = Math.floor(Date.now() / 1000); + + if (!skipMinimumPackageAge()) { + cutoff = cutoff - (getMinimumPackageAgeHours() * 3600); + } + + return { + permission_group: { + id: 1, + name: "Default", + }, + ecosystems: { + npm: { + block_all_installs: false, + request_installs: false, + minimum_allowed_age_timestamp: cutoff, + exceptions: { + allowed_packages: [], + rejected_packages: [], + }, + }, + pypi: { + block_all_installs: false, + request_installs: false, + minimum_allowed_age_timestamp: cutoff, + exceptions: { + allowed_packages: [], + rejected_packages: [], + }, + }, + }, + }; +} + +/* + +# Reference: config file format. + +```json +{ + "permission_group": { + "id": 18, + "name": "Default" + }, + "ecosystems": { + "npm": { + "block_all_installs": false, + "request_installs": false, + "minimum_allowed_age_timestamp": 1778143932, + "exceptions": { + "allowed_packages": [], + "rejected_packages": [] + } + }, + "pypi": { + "block_all_installs": false, + "request_installs": false, + "minimum_allowed_age_timestamp": 1778057532, + "exceptions": { + "allowed_packages": [], + "rejected_packages": [] + } + } + } +} +``` + +*/ diff --git a/packages/safe-chain/src/registryProxy/ramaProxy/createRamaProxy.js b/packages/safe-chain/src/registryProxy/ramaProxy/createRamaProxy.js index 6d98bce1..e8d70334 100644 --- a/packages/safe-chain/src/registryProxy/ramaProxy/createRamaProxy.js +++ b/packages/safe-chain/src/registryProxy/ramaProxy/createRamaProxy.js @@ -8,6 +8,7 @@ import { ui } from "../../environment/userInteraction.js"; import { getLoggingLevel, LOGGING_VERBOSE } from "../../config/settings.js"; import { getReportingServer } from "./reportingServer.js"; import EventEmitter from "node:events"; +import { createAikidoEndpointConfigFile } from "./createAikidoEndpointConfigFile.js"; const readFilePromise = promisify(readFile); @@ -90,7 +91,7 @@ export function createRamaProxy(ramaPath) { * @returns {Promise} */ async function startRama(ramaPath, dataFolder, reportingUrl) { - const startTime = Date.now(); + const startTime = Date.now(); const args = [ "--secrets", "memory", @@ -99,6 +100,12 @@ async function startRama(ramaPath, dataFolder, reportingUrl) { "--reporting-endpoint", reportingUrl, ]; + + const configFile = await createAikidoEndpointConfigFile(dataFolder); + if (configFile) { + args.push("--config-file", configFile); + } + const stdio = getLoggingLevel() === LOGGING_VERBOSE ? "inherit" : "pipe"; const process = spawn(ramaPath, args, { stdio: stdio }); diff --git a/packages/safe-chain/src/registryProxy/ramaProxy/createRamaProxy.spec.js b/packages/safe-chain/src/registryProxy/ramaProxy/createRamaProxy.spec.js index e0c6eb8f..70c0451a 100644 --- a/packages/safe-chain/src/registryProxy/ramaProxy/createRamaProxy.spec.js +++ b/packages/safe-chain/src/registryProxy/ramaProxy/createRamaProxy.spec.js @@ -24,6 +24,7 @@ mock.module("node:child_process", { }); const mockExistsSync = mock.fn(() => true); +const mockWriteFile = mock.fn(() => {}); const mockMkdtempSync = mock.fn(() => "/tmp/safe-chain-proxy-abc"); const mockReadFile = mock.fn( (/** @type {string} */ path, /** @type {string} */ _encoding, /** @type {Function} */ cb) => { @@ -42,6 +43,7 @@ mock.module("node:fs", { existsSync: mockExistsSync, mkdtempSync: mockMkdtempSync, readFile: mockReadFile, + writeFile: mockWriteFile, }, }); @@ -56,6 +58,12 @@ mock.module("../../config/settings.js", { }, }); +mock.module("./createAikidoEndpointConfigFile.js", { + namedExports: { + createAikidoEndpointConfigFile: () => "/path/to/config-file.json" + } +}) + const mockFetch = mock.method(globalThis, "fetch", async () => ({ text: async () => "MOCK_CA_CERT_PEM", }));