Running Commands from Apache as different user
Posted on 2011-06-07 08:56:02
by Geert Vandeweyer
Running system commands from a web interface is very usefull to build for example a front-end to some long-running jobs on your server. I use it for example to start & monitor updates of some database tables taking a few hours. Since the regular apache user on Ubuntu has very limited privileges, I launch these jobs as a different user. Another application is sending jobs to a torque/pbs server, again as a user with more privileges to read & write certain files.
To get this running, you best create a dedicated user, with specific sudoers permissions, but no full admin rights. The needed steps are listed below. You need to be root to edit sudoers files, so be very carefull ! You can also perform these steps with sudo.
1. Create dedicated user
Create the user using the useradd command. The -m options creates the home directory. This allows any process to create configuration files etc. You can use a random password, which will be read from database or from a configuration file.
root@ubuntu: useradd -m -p PASSWORD USERNAME
2. Determine apache user
First, you need to find out what the default apache user is. Some of the defaults are wwwrun, www-data or apache. Use the 'id' command to check for an existing user. If the defaults do not exist, check your distributions apache docs for more info.
root@ubuntu: id www-data
uid=33(www-data) gid=33(www-data) groups=33(www-data)
3. Determine sudoers structure
The sudoers file contains specific permissions for specified users or groups. We will specify here that the apache user is allowed to switch user (su) to the user specified above, if the password of the target user is specified. This is important, since some distros, such as Ubuntu ask for the source user password by default.
On Ubuntu and most modern distributions, sudo reads files located in /etc/sudoers.d to load additional configurations. If this directory exist, create a file in this directory named as the created user. Then open it with your favorite editor.
root@ubuntu: touch /etc/sudoers.d/USERNAME
If you do not have this directory, you will have to edit the main sudoers file in /etc/sudoers. Do not edit this file just like that, use visudo !
root@ubuntu: visudo
4. Add permission statements to sudoers file
Add the following lines to the sudoers file opened in step 3. Replace 'APACHEUSER' with the user from step 2 and 'USERNAME' with the user from step 1.
APACHEUSER ALL=(USERNAME) ALL
Defaults:APACHEUSER targetpw
Defaults:APACHEUSER !requiretty
The first line allows the apache user to sudo only to the specified username, and can run any command afterwards. The next lines specifies the default beheaviour for the listed users, here the apache user. First it states that the apache user needs to specify the target password when using sudo. Then it states that the apache user does not need an interactive tty to log in. By specifying this, we can pipe the password to the sudo command.
5. Set permissions
If you created a file in /etc/sudoers.d/, you need to set the permissions to 0440. If you used visudo, you can skip this.
root@ubuntu: chmod 0440 /etc/sudoers.d/USERNAME
6. Store the password
I would recommend to store the password of the user from step 1 in a database or a configuration file kept outside your web directory. For example a file called /etc/webcredentials, with can be owned by apache user and readable only by that user.
root@ubuntu: touch /etc/webcredentials
root@ubuntu: chown apacheuser:apacheuser /etc/webcredentials
Then add these lines to the file:
SCRIPTUSER=username
SCRIPTPASS=password
7. Run commands from PHP
A short example script to use this configuration is included. This command launches a program that outputs to a file in the web-directory. It then redirects to another page, where you can for example periodically read the output file and check for a completion status (from the 'status' file)
$line) {
# Skip Comments
if ( ! preg_match("/#.*/", $line) ) {
# Only process non-empty lines
if ( preg_match("/S/", $line) ) {
list( $key, $value ) = explode( "=", trim( $line ), 2);
$config[$key] = $value;
}
}
}
$user = $config['SCRIPTUSER'];
$pass = $config['SCRIPTPASS'];
####################
## LAUNCH COMMAND ##
####################
# prepare output file
$fh = fopen($outdir."output,'w');
fwrite($fh,"Starting up");
fclose($fh);
system("chmod 777 $outdir"."output");
# lauch : print '1' to status file at beginning, '0' when finished. redirect all output to outfile.
$command = "(COLUMNS=1024 && echo "1" > $statusfile && echo $pass | sudo -u $user -S bash -c "COLUMNS=1024 && /usr/bin/LongRunningCommand >> $outdir"."output" && echo "0" > $statusfile && chmod a+rw $statusfile) > /dev/null & ";
system($command);
##############
## REDIRECT ##
##############
header("Location: index.php?page=result");
?>
Apache, Password, PHP, sudoers, Ubuntu
Comments
Loading Comments