Allow Apache to run a command as a different user

I have a script that executes several commands in a user's home directory. The files are owned by the user and Apache (the www-data group) only has read privileges to them. The script needs to be executed on demand by PHP via exec(), and performs some deletions / untarring of files, which fail since Apache doesn't have write permissions to the directories.

I've tried editing the sudoers file like this :

www-data ALL=(user) NOPASSWD: /bin/su user -c /home/user/bin/script.sh

but it prompts me for the user's password

I've also tried

www-data ALL=(root) NOPASSWD: /usr/bin/sudo su user -c /home/user/bin/script.sh

but that prompts for www-data's sudo password

How to I get this to work without a password ?


Finally got it working with this line :

www-data ALL=(ALL) NOPASSWD: /usr/bin/sudo -u user /home/user/bin/script.sh

Since I needed arguments to my script, I had to add a "shell-style wildcard" at the end of the line :

www-data ALL=(ALL) NOPASSWD: /usr/bin/sudo -u user /home/user/bin/script.sh [[\:alpha\:]]*

It's not exactly what I was looking for, but it works (ie. it happens that my arguments start with alphabetic characters, but in fact I would like the expression to match only alphanumeric characters, dashes and periods).

I'm not at all familiar with shell wildcards and POSIX character classes, the one I use is basically copy-pasted from the sudoers manual. Anyone who knows how these apply to this kind of problem, please leave your comments !


Why are you running su inside sudo? (or worse, sudo inside sudo)

www-data ALL=(user) NOPASSWD: /bin/bash /home/user/bin/script.sh

This should work.


If it weren't a script, you could've just suid'd the executable, and set the group & permissions so only the webserver could execute it.

You can also use suExec (apache only) or CGIWrap (any webserver) to run CGIs under other users. There's also suPHP specifically for PHP in non-CGI mode on Apache.

They offer slightly different options (eg, CGIwrap can set resource limits), but in general, they'll run programs as alternate users.


I've made a different approach to this, to allow the apache user to sudo to a specified user that can then run all commands (or you can specify a list if you only need one or a few.

APACHEUSER        ALL=(USERNAME)        ALL
Defaults:APACHEUSER       targetpw
Defaults:APACHEUSER             !requiretty

this allows the password to be sent from code (eg read from database) using :

echo password | sudo -u username -S bash -c command_here arguments_here

Just make sure you use a dedicated user for this, and don't put that user in the wheel group.

see also here

geert