Search code examples
bashnginxubuntu-16.04fastcgisudoers

Using sudoers to restrict script files for www-data? (nohup)


I am trying to invoke a bash script requiring sudo upon receiving a web service call using FCGI Wrap and NGINX.

I have two scripts, one calling the other. The 'outer' one is meant to be called by the web service and return immediately. While the 'inner' one is called from the 'outer', completes asynchronously and requires some sudo privileges to execute some commands.

When the web service call is made, FCGI Wrap and NGINX are configured to use the 'www-data' user. I need www-data to be able to call only a few scripts with sudo privileges, passwordlessly.

I am running Ubuntu 16.04

I have a file in the /etc/sudoers.d/ directory with 0440 permissions. To allow www-data to run the scripts. I've tried several configurations, but the only one I can get to work is:

www-data ALL= NOPASSWD: ALL

However this is too much of an exposure, I only need it to use scripts in a single directory: /opt/myapp/bin/ (... or maybe two? /var/www/scripts/ AND /opt/myapp/bin/) This is what I think I'd like to get working:

www-data ALL= NOPASSWD: /opt/myapp/bin/

In NGINX I have this location to route to the script:

location /scripts/ {
    root /var/www;
    fastcgi_intercept_errors on;
    include /etc/nginx/fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_pass unix:/var/run/fcgiwrap.socket;
}

Outer script: /var/www/scripts/upgrade.sh

#!/bin/bash
echo "Content-type: text/html"
echo ""    
echo "Beginning Upgrade"
sudo nohup /opt/myapp/bin/upgrade_myapp.sh >> /var/log/myapp/upgrade.log 2>&1 &
exit 0

Inner script: /opt/myapp/bin/upgrade_myapp.sh

#!/bin/bash
echo "[$(date)] : Beginning Upgrade"
echo "[$(date)] : stuff requiring sudo..."
echo "[$(date)] : Completed Upgrade Successfully"
exit 0

When I browse to the web service, the 'outer' script runs and I log this error:

 sudo: no tty present and no askpass program specified

When I try to run the file directly with www-data I get prompted for a password:

 sudo -u www-data ./upgrade.sh

Everything runs successfully if I execute it directly with my regular user with full sudo capability.

 sudo ./upgrade.sh

What changes do I need to make to allow www-data user to call the 'inner' script with sudo, so that it can run the commands within, but not expose more access then necessary?

Some other sudoers I've tried:

www-data ALL=NOPASSWD: /opt/myapp/bin/upgrade_myapp.sh 

www-data ALL= NOPASSWD: /var/www/scripts/upgrade.sh, /opt/myapp/bin/upgrade_myapp.sh 

www-data ALL=(ALL) NOPASSWD: /var/www/scripts/
www-data ALL=(ALL) NOPASSWD: /opt/myapp/bin/

www-data ALL=(ALL) NOPASSWD: /var/www/scripts/upgrade.sh
www-data ALL=(ALL) NOPASSWD: /opt/myapp/bin/upgrade_myapp.sh 

www-data ALL=NOPASSWD: /opt/myapp/bin/*, /var/www/scripts/*

UPDATE It appears my problem is nohup. Removing nohup makes this work. sudo is trying to act on nohup not the file, but my sudoers file does not include nohup. I am currently looking to determine if I need nohup, or can i use sudoers to say I want to allow nohup but only with these files.


Solution

  • this line in the sudoers means www-data can sudo nohup commands with only files in this folder as parameters, passwordless:

    www-data ALL = (root) NOPASSWD: /usr/bin/nohup /opt/myapp/bin/*