Skip to content

Commit

Permalink
Angus/backport 98 (#102)
Browse files Browse the repository at this point in the history
* backport #98

* version bump
  • Loading branch information
veggiesaurus committed Nov 25, 2021
1 parent e9ffc79 commit c072b1b
Show file tree
Hide file tree
Showing 7 changed files with 73 additions and 35 deletions.
5 changes: 5 additions & 0 deletions config/config_schema.json
Expand Up @@ -455,6 +455,11 @@
],
"default": "/usr/bin/carta_backend"
},
"preserveEnv": {
"description": "Use the --preserve-env argument when calling sudo",
"type": "boolean",
"default": true
},
"killCommand": {
"description": "Path to CARTA kill script",
"type": "string",
Expand Down
5 changes: 4 additions & 1 deletion docs/src/configuration.rst
Expand Up @@ -26,7 +26,10 @@ To provide the ``carta`` user with these privileges, you must make modifications

.. warning::
Please only edit your sudoers configuration with ``visudo`` or equivalent.


.. note::
Older versions of ``sudo`` do not support the ``--preserve-env=VARIABLE`` argument. If your version of ``sudo`` is too old, set ``"preserveEnv"`` to ``false`` in your controller configuration, and add ``Defaults env_keep += "CARTA_AUTH_TOKEN"`` to your sudoers configuration.

.. _config-authentication:

Authentication
Expand Down
5 changes: 3 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
@@ -1,6 +1,6 @@
{
"name": "carta-controller",
"version": "2.0.4",
"version": "2.0.5",
"description": "NodeJS-based controller for CARTA",
"repository": "https://github.com/CARTAvis/carta-controller",
"homepage": "https://www.cartavis.org",
Expand Down
51 changes: 32 additions & 19 deletions src/controllerTests.ts
Expand Up @@ -28,23 +28,21 @@ export async function runTests(username: string) {
}
await testDatabase();
if (ServerConfig.logFileTemplate) {
testLog(username);
await testLog(username);
}
testFrontend();
const backendProcess = await testBackendStartup(username);
await testKillScript(username, backendProcess);
}

function testLog(username: string) {
const logLocation = ServerConfig.logFileTemplate
.replace("{username}", username)
.replace("{pid}", "9999")
.replace("{datetime}", moment().format("YYYYMMDD.h_mm_ss"));
async function testLog(username: string) {
const logLocation = ServerConfig.logFileTemplate.replace("{username}", username).replace("{pid}", "9999").replace("{datetime}", moment().format("YYYYMMDD.h_mm_ss"));

try {
const logStream = fs.createWriteStream(logLocation, {flags: "a"});
logStream.write("test");
logStream.close();
// Transform callbacks into awaits
await new Promise(res => logStream.write("test", res));
await new Promise(res => logStream.end(res));
fs.unlinkSync(logLocation);
console.log(logSymbols.success, `Checked log writing for user ${username}`);
} catch (err) {
Expand Down Expand Up @@ -167,25 +165,40 @@ function testFrontend() {

async function testBackendStartup(username: string) {
const port = ServerConfig.backendPorts.max - 1;
let args = [
"--preserve-env=CARTA_AUTH_TOKEN",
"-u", `${username}`,

let args: string[] = [];
if (ServerConfig.preserveEnv) {
args.push("--preserve-env=CARTA_AUTH_TOKEN");
}

args = args.concat([
"-n", // run non-interactively. If password is required, sudo will bail
"-u",
`${username}`,
ServerConfig.processCommand,
"--no_http", "true",
"--debug_no_auth", "true",
"--no_log", ServerConfig.logFileTemplate ? "true" : "false",
"--port", `${port}`,
"--top_level_folder", ServerConfig.rootFolderTemplate.replace("{username}", username),
ServerConfig.baseFolderTemplate.replace("{username}", username),
];
"--no_http",
"--debug_no_auth",
"--port",
`${port}`,
"--top_level_folder",
ServerConfig.rootFolderTemplate.replace("{username}", username)
]);

if (ServerConfig.logFileTemplate) {
args.push("--no_log");
}

if (ServerConfig.additionalArgs) {
args = args.concat(ServerConfig.additionalArgs);
}

// Finally, add the positional argument for the base folder
args.push(ServerConfig.baseFolderTemplate.replace("{username}", username));

verboseLog(`running sudo ${args.join(" ")}`);

const backendProcess = spawn("sudo", args);
// Use same stdout and stderr stream for the backend process
const backendProcess = spawn("sudo", args, {stdio: "inherit"});
await delay(2000);
if (backendProcess.signalCode) {
throw new Error(`Backend process terminated with code ${backendProcess.signalCode}. Please check your sudoers config, processCommand option and additionalArgs section`);
Expand Down
35 changes: 24 additions & 11 deletions src/serverHandlers.ts
Expand Up @@ -179,21 +179,34 @@ async function startServer(username: string) {
throw {statusCode: 500, message: "No available ports for the backend process"};
}

let args = [
"--preserve-env=CARTA_AUTH_TOKEN",
"-u", `${username}`,
let args: string[] = [];
if (ServerConfig.preserveEnv) {
args.push("--preserve-env=CARTA_AUTH_TOKEN");
}

args = args.concat([
"-n", // run non-interactively. If password is required, sudo will bail
"-u",
`${username}`,
ServerConfig.processCommand,
"--no_http", "true",
"--no_log", ServerConfig.logFileTemplate ? "true" : "false",
"--port", `${port}`,
"--top_level_folder", ServerConfig.rootFolderTemplate.replace("{username}", username),
ServerConfig.baseFolderTemplate.replace("{username}", username),
];
"--no_http",
"--port",
`${port}`,
"--top_level_folder",
ServerConfig.rootFolderTemplate.replace("{username}", username)
]);

if (ServerConfig.logFileTemplate) {
args.push("--no_log");
}

if (ServerConfig.additionalArgs) {
args = args.concat(ServerConfig.additionalArgs);
}

// Finally, add the positional argument for the base folder
args.push(ServerConfig.baseFolderTemplate.replace("{username}", username));

const headerToken = v4();
const child = spawn("sudo", args, {env: {CARTA_AUTH_TOKEN: headerToken}});
setPendingProcess(username, port, headerToken, child);
Expand Down Expand Up @@ -241,7 +254,7 @@ async function startServer(username: string) {
child.on("exit", code => {
console.log(`Process ${child.pid} exited with code ${code} and signal ${child.signalCode}`);
deleteProcess(username);
logStream?.close();
logStream?.end();
});

// Check for early exit of backend process
Expand All @@ -256,7 +269,7 @@ async function startServer(username: string) {
} catch (e) {
verboseError(e);
console.log(`Problem starting process for user ${username}`);
logStream?.close();
logStream?.end();
if (e.statusCode && e.message) {
throw e;
} else {
Expand Down
5 changes: 4 additions & 1 deletion src/types.ts
Expand Up @@ -65,8 +65,11 @@ export interface CartaServerConfig {
backendPorts: {
min: number;
max: number;
}
};
// Command to execute when starting the backend process
processCommand: string;
// Use the --preserveEnv argument when calling sudo
preserveEnv: boolean;
// The {username} placeholder will be replaced with the username
rootFolderTemplate: string;
baseFolderTemplate: string;
Expand Down

0 comments on commit c072b1b

Please sign in to comment.