On occasion, the user initiates an action in my Node app that requires escalated administrator or root privileges. Rather than ask users to run the app with sudo
, I would like to prompt the user for their password and escalate the privileges of the already-running Node process.
I am not interested in my app executing a child process with sudo
(as is already possible with sudo-prompt). I want the node process itself to gain root privileges after having been started by a non-root user without sudo
.
One example of an app that displays behavior exhibiting the problem:
var process = require('process');
var http = require('http');
var server = http.createServer(...);
// Several steps here that are unsafe to run as root
promptUserForAdminPassword();
server.listen(80); // Fails, needs to be root
I would like to write the function promptUserForAdminPassword()
, which would prompt the user for their password, escalating the privileges of Node so it can run server.listen(80)
with root privileges, but run everything prior with user privileges.
You are essentially wanting to change the uid
of the node process to 0, the id for root. This is done using Node's process.setuid(0)
, but only root
or processes run with sudo
will be successful with that call, so this is not possible.
It is not possible for a process with a uid
of a non-privileged user to change its uid
to 0.
// Prompts user for password in terminal running Node process
child_process.spawn('sudo', ['node', 'serverlistener.js']);
// Prompts user for password using UI element
child_process.spawn('gksudo', ['node', 'serverlistener.js']);
This question has some options for the missing gksudo
on macOS.
If starting the app with sudo
is a possibility, you can reduce the exposure of root by:
Example:
var userid = require('userid');
var sudoUserId = userid.uid(process.env.SUDO_USER);
process.seteuid(sudoUserId);
// Do things
process.seteuid(0);
server.listen(80);
Uses userid module.