Proper way to perform privileged tasks from wsgi app - python

I need to write a small wsgi app for manipulating iptables. I use nginx + uwsgi on Debian with python-iptables package.
uwsgi runs as www-data user by default, so if I try to access iptables from my app I got iptc.ip4tc.IPTCError: can't initialize filter: Permission denied (you must be root).
Is there any workaround to this problem except running the whole wsgi app as root? And what should I do if I want to integrate my app with Django (I definitely don't want run all Django stuff as root)?

You could try to exctract all the functionality which needs superuser privileges into separate script (for example script.py) owned by root (chown root script.py), allow exectution of it (chmod u+x script.py), then set setuid to allow execution rights on that file with root permissions to other users (chmod u+s script.py).
Then you should be able to call that script from your wsgi application using subprocess and www-data privileges.

Related

Deploy Flask app on Apache Server using mod_wsgi and WinSCP

I want to deploy my Flask application on an Apache server. I have an account on the server, and have been told that "The server can be used to run scripts and web apps written in Python (using django and mod_wsgi)".
I am on Windows, and to transfer files I have to use an FTP client - so I am using WinSCP.
Installing mod_wsgi is not as straightforward as I expected and I cannot get any clear documentation online.
Because the server can already run Python scripts using mod_wsgi does that mean that I just have to create a .wsgi file or do I still need to download it?
I don't know how to go about this.
First you need to check if mod_wsgi is really enabled on the server, then you have to check how your virtual host is configured in apache. There you will find the name you have to give to the wsgi file.
If you have shell access to the server you can do that by using the following commands:
Check mod_wsgi:
sudo apache2ctl -t -D DUMP_MODULES | grep wsgi
Check what name the .wsgi file should have:
sudo grep WSGIScriptAlias /etc/apache2/sites-enabled/yoursite.conf

Changing default permission in Flask application with Apache web server

I have a flask application that creates directory with this code:
if not os.path.exists(target_path):
os.makedirs(target_path)
With the created directory the default permission is 0755, and the owner and group is _www.
So, only the owner can write in the directory.
I always have to modify the permission manually to 0775 to make some files in it.
How to make the default directory permission as 0775? I use apache for web server.
This has something to do with Apache setup.
For Mac:
Open /System/Library/LaunchDaemons/org.apache.httpd.plist
Add <key>Umask</key> and <integer>002</integer>
Restart with sudo apachectl restart
I found the solution from this site, for linux I guess Setting the umask of the Apache user can give some hints.
Change the code to
if not os.path.exists(target_path):
os.makedirs(target_path, mode=0775)

Flask can't see sqlite db when launched via uWSGI Emperor

When I run my Flask app via uWSGI emperor, it 502's out with a Sqlite error regarding it not being able to see my tables. I can go in via the sqlite3 command and verify the data is there. When I run the site via
uwsgi --ini site_conf.ini
it works just fine, but not via emperer.
Check you are not using relative paths when referring to the sqlite db. When run by the Emperor the cwd changes to the vassals dir. Eventually use chdir option in your vassal to move to a specific directory

python change privileges to restart external application

Hi I have a python script which modifies an application configuration file. To applied this, I need to restart the application. To do that I call a init.d file. But I need to be root when I do this action otherwise the application cannot bind her on the port. Also I dont want execute all my python script with the root's privileges. How can I execute the restart with the root privileges and then remove them.
I set the user permission at the beginning with:
if __name__ == "__main__":
uid = pwd.getpwnam('ubuntu')[2]
os.setuid(uid)
app.run(host='0.0.0.0', port=5001, debug=True)
and at the end of my script I need to execute:
commands.getoutput('/etc/init.d/webapplication restart')
webapplication binds on the port 80.
If I execute my script with this configuration, webapplication cant start and return a message, "cannot bind socket on the 80".
Any idea? to have a clean solution to execute only one external command with the root privileges on a Debian server under a python script?
Thansk in advance.
P.S: I have tried to use the same method like in my main function and I have replaced the user "ubuntu" by "root" but it's not work.
You can use either of two approaches:
Create a program whose only job is to run the init.d script, and make it setuid root. (Make sure to write it securely!). The main script runs with ordinary user permissions and calls the runner.
There's no way for a program to escalate its own privileges (except by running sudo, which is at least as expensive as approach 1), but a program running as root can de-escalate itself. So you can do some steps as root and then continue as the normal user by setting your uid down to the real uid. This won't be any help if you need root privileges for the last thing the program does, though.
Finaly to reach my goal, I have use the sudo solution. To do that on a debian server:
apt-get install sudo
Edit: /etc/sudoers
Add line: my_user(uses for the setuid) ALL = NOPASSWD : /etc/init.d/webapplication
And in my python script:
commands.getoutput('sudo /etc/init.d/webapplication restart')
And that works.

Running subversion under apache and mod_python

My Apache server runs on some non-default (not-root) account. When it tries to run a python script which in turn executes a subversion check-out command, 'svn checkout' fails with the following error message:
svn: Can't open file '/root/.subversion/servers': Permission denied
At the same time running that python script with subversion checkout command inside from command line under the same user account goes on perfectly well.
Apache server 2.2.6 with mod_python 3.2.8 runs on Fedora Core 6 machine.
Can anybody help me out? Thanks a lot.
It sounds like the environment you apache process is running under is a little unusual. For whatever reason, svn seems to think the user configuration files it needs are in /root. You can avoid having svn use the root versions of the files by specifying on the command line which config directory to use, like so:
svn --config-dir /home/myuser/.subversion checkout http://example.com/path
While not fixing your enviornment, it will at least allow you to have your script run properly...
Try granting the Apache user (the user that the apache service is running under) r+w permissions on that file.
Doesn't Apache's error log give you a clue?
Maybe it has to do with SELinux. Check /var/log/audit/audit.log and adjust your SELinux configuration accordingly, if the audit.log file indicates that it's SELinux which denies Apache access.
The Permission Denied error is showing that the script is running with root credentials, because it's looking in root's home dir for files.
I suggest you change the hook script to something that does:
id > /tmp/id
so that you can check the results of that to make sure what the uid/gid and euid/egid are. You will probably find it's not actually running as the user you think it is.
My first guess, like Troels, was also SELinux, but that would only be my guess if you are absolutely sure the script through Apache is running with exactly the same user/group as your manual test.
Well, thanks to all who answered the question. Anyway, I think I solved the mistery.
SELinux is completely disabled on the machine, so the problem is definitely in 'svn co' not being able to found config_dir for the user account it runs under.
Apache / mod_python doesn't read in shell environment of the user account which apache is running on. Thus for examle no $HOME is seen by mod_python when apache
is running under some real user ( not nobody )
Now 'svn co' has a flag --config-dir which points to configuration directory to read params from. By default it is $HOME/.subversion, i.e. it corresponds to the user account home directory. Apparently when no $HOME exists mod_python goes to root home dir ( /root) and tries to fiddle with .subversion content over there - which is obviously
fails miserably.
putting
SetEnv HOME /home/qa
into the /etc/httpd/conf/httpd.conf doesn't solve the problem because of SetEnv having nothing to do with shell environment - it only sets apache related environment
Likewise PythonOption - sets only mod_python related variables which can be read with req.get_options() after that
Running 'svn co --config-dir /home/ ...' definitely gives a workaround for running from within mod_python, but gets in the way of those who will try to run the script from command line.
So the proposed ( and working) solution is to set HOME environment variable prior to starting appache.
For example in /etc/init.d/httpd script
QAHOME=/home/qa
...
HOME=$QAHOME LANG=$HTTPD_LANG daemon $httpd $OPTIONS
What is happening is apache is being started with the environment variables of root, so it thinks that it should find its config files in /root/. This is NOT the case.
what happens is if you do sudo apache2ctl start, it pulls your $HOME variable from the sudo $HOME=/root/
I have just found a solution to this problem myself (although with mod_perl, but same thing)
run this command (if its apache 1, remove the 2):
sudo /etc/init.d/apache2 stop
sudo /etc/init.d/apache2 start
When /etc/init.d/apache2 starts apache, it sets all the proper environment variables that apache should be running under.

Categories

Resources