Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

adjustments to sudo call and log test #98

Merged
merged 5 commits into from
Nov 5, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions config/config_schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,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
Original file line number Diff line number Diff line change
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
38 changes: 24 additions & 14 deletions src/controllerTests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,20 +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) {
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 @@ -163,31 +164,40 @@ function testFrontend() {

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

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)
];
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
28 changes: 18 additions & 10 deletions src/serverHandlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,26 +178,34 @@ async function startServer(username: string) {
throw {statusCode: 500, message: "No available ports for the backend process"};
}

let args = [
"--preserve-env=CARTA_AUTH_TOKEN",
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)
];
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 @@ -242,7 +250,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 @@ -257,7 +265,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
3 changes: 3 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,10 @@ export interface CartaServerConfig {
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