From 2aef0d4f5840c51038703bfe28ab266df693e0f6 Mon Sep 17 00:00:00 2001 From: veggiesaurus Date: Wed, 20 Oct 2021 21:39:37 +0200 Subject: [PATCH 1/4] adjustments to sudo call and log test --- config/example_sudoers_conf.stub | 3 +++ package-lock.json | 4 ++-- package.json | 2 +- src/controllerTests.ts | 28 ++++++++++++++++------------ src/serverHandlers.ts | 19 +++++++++++-------- 5 files changed, 33 insertions(+), 23 deletions(-) diff --git a/config/example_sudoers_conf.stub b/config/example_sudoers_conf.stub index cb6ee75..d85d1c7 100644 --- a/config/example_sudoers_conf.stub +++ b/config/example_sudoers_conf.stub @@ -1,5 +1,8 @@ # customise this file to fit your environment using visudo /etc/sudoers.d/carta_controller +# ensure the auth token environmental variable is persisted across the sudo call +Defaults env_keep += "CARTA_AUTH_TOKEN" + # carta user can run the carta_backend command as any user in the carta-users group without entering password carta ALL=(%carta-users) NOPASSWD:SETENV: /usr/bin/carta_backend diff --git a/package-lock.json b/package-lock.json index b22bd72..d6070ec 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "carta-controller", - "version": "3.0.0-beta.1c", + "version": "3.0.0-beta.1d", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "carta-controller", - "version": "3.0.0-beta.1c", + "version": "3.0.0-beta.1d", "license": "ISC", "dependencies": { "@pm2/io": "^5.0.0", diff --git a/package.json b/package.json index 9f5977c..3b9ad0f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "carta-controller", - "version": "3.0.0-beta.1c", + "version": "3.0.0-beta.1d", "description": "NodeJS-based controller for CARTA", "repository": "https://github.com/CARTAvis/carta-controller", "homepage": "https://www.cartavis.org", diff --git a/src/controllerTests.ts b/src/controllerTests.ts index d02927b..2119d12 100644 --- a/src/controllerTests.ts +++ b/src/controllerTests.ts @@ -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) { @@ -164,30 +165,33 @@ function testFrontend() { async function testBackendStartup(username: string) { const port = ServerConfig.backendPorts.max - 1; let args = [ - "--preserve-env=CARTA_AUTH_TOKEN", + "-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`); diff --git a/src/serverHandlers.ts b/src/serverHandlers.ts index 67b6304..95e95f9 100644 --- a/src/serverHandlers.ts +++ b/src/serverHandlers.ts @@ -179,25 +179,28 @@ async function startServer(username: string) { } let args = [ - "--preserve-env=CARTA_AUTH_TOKEN", + "-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); @@ -242,7 +245,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 @@ -257,7 +260,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 { From 836ba1a500cac6086e2daa7e234f31399f010d63 Mon Sep 17 00:00:00 2001 From: veggiesaurus Date: Fri, 5 Nov 2021 11:10:14 +0200 Subject: [PATCH 2/4] revert version change --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index d6070ec..b22bd72 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "carta-controller", - "version": "3.0.0-beta.1d", + "version": "3.0.0-beta.1c", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "carta-controller", - "version": "3.0.0-beta.1d", + "version": "3.0.0-beta.1c", "license": "ISC", "dependencies": { "@pm2/io": "^5.0.0", diff --git a/package.json b/package.json index 3b9ad0f..9f5977c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "carta-controller", - "version": "3.0.0-beta.1d", + "version": "3.0.0-beta.1c", "description": "NodeJS-based controller for CARTA", "repository": "https://github.com/CARTAvis/carta-controller", "homepage": "https://www.cartavis.org", From 3f14eea307afc1c9b9d6de458bc658b577232410 Mon Sep 17 00:00:00 2001 From: veggiesaurus Date: Fri, 5 Nov 2021 12:45:49 +0200 Subject: [PATCH 3/4] adds preserveEnv config option (defaults to true) --- config/config_schema.json | 5 +++++ docs/src/configuration.rst | 5 ++++- src/controllerTests.ts | 10 ++++++++-- src/serverHandlers.ts | 9 +++++++-- src/types.ts | 3 +++ 5 files changed, 27 insertions(+), 5 deletions(-) diff --git a/config/config_schema.json b/config/config_schema.json index 8e28841..a1c9046 100644 --- a/config/config_schema.json +++ b/config/config_schema.json @@ -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", diff --git a/docs/src/configuration.rst b/docs/src/configuration.rst index 2df308e..91b8ff1 100644 --- a/docs/src/configuration.rst +++ b/docs/src/configuration.rst @@ -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. + .. _config-authentication: Authentication diff --git a/src/controllerTests.ts b/src/controllerTests.ts index 2119d12..82c8650 100644 --- a/src/controllerTests.ts +++ b/src/controllerTests.ts @@ -164,7 +164,13 @@ function testFrontend() { async function testBackendStartup(username: string) { const port = ServerConfig.backendPorts.max - 1; - let args = [ + + 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}`, @@ -175,7 +181,7 @@ async function testBackendStartup(username: string) { `${port}`, "--top_level_folder", ServerConfig.rootFolderTemplate.replace("{username}", username) - ]; + ]); if (ServerConfig.logFileTemplate) { args.push("--no_log"); diff --git a/src/serverHandlers.ts b/src/serverHandlers.ts index 95e95f9..81e2169 100644 --- a/src/serverHandlers.ts +++ b/src/serverHandlers.ts @@ -178,7 +178,12 @@ async function startServer(username: string) { throw {statusCode: 500, message: "No available ports for the backend process"}; } - let args = [ + 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}`, @@ -188,7 +193,7 @@ async function startServer(username: string) { `${port}`, "--top_level_folder", ServerConfig.rootFolderTemplate.replace("{username}", username) - ]; + ]); if (ServerConfig.logFileTemplate) { args.push("--no_log"); diff --git a/src/types.ts b/src/types.ts index 5e08f32..e5b158d 100644 --- a/src/types.ts +++ b/src/types.ts @@ -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; From ac21f1dc3ed6bccee27755cb973451a877720fbc Mon Sep 17 00:00:00 2001 From: veggiesaurus Date: Fri, 5 Nov 2021 13:10:10 +0200 Subject: [PATCH 4/4] remove env_keep entry from example sudoers conf --- config/example_sudoers_conf.stub | 3 --- docs/src/configuration.rst | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/config/example_sudoers_conf.stub b/config/example_sudoers_conf.stub index d85d1c7..cb6ee75 100644 --- a/config/example_sudoers_conf.stub +++ b/config/example_sudoers_conf.stub @@ -1,8 +1,5 @@ # customise this file to fit your environment using visudo /etc/sudoers.d/carta_controller -# ensure the auth token environmental variable is persisted across the sudo call -Defaults env_keep += "CARTA_AUTH_TOKEN" - # carta user can run the carta_backend command as any user in the carta-users group without entering password carta ALL=(%carta-users) NOPASSWD:SETENV: /usr/bin/carta_backend diff --git a/docs/src/configuration.rst b/docs/src/configuration.rst index 91b8ff1..93f00f4 100644 --- a/docs/src/configuration.rst +++ b/docs/src/configuration.rst @@ -28,7 +28,7 @@ To provide the ``carta`` user with these privileges, you must make modifications 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. + 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: