Running commands from within python that need root access - python

I have been playing around with subprocess lately. As I do more and more; I find myself needing root access. I was wondering if there is an easy way to enter the root password for a command that needs it with subprocess module. So when I am prompted for the password my script and provide it and run the command. I know this is bad practice by where the code will be running is sandboxed and separate from the rest of the system; I also dont want to be running as root.
I would really appreciate small example if possible. I know you can do this with expect, but i am looking something more python centric. I know pexpect exsists but its a bit overkill for this simple task.
Thanks.

It would probably be best to leverage sudo for the user running the Python program. You can specify specific commands and arguments that can be run from sudo without requiring a password. Here is an example:
There are many approaches but I prefer the one that assigns command sets to groups. So let's say we want to create a group to allow people to run tcpdump as root. So let's call that group tcpdumpers.
First you would create a group called tcpdumpers. Then modify /etc/sudoers (using the visudo command):
# Command alias for tcpdump
Cmnd_Alias TCPDUMP = /usr/sbin/tcpdump
# This is the group that is allowed to run tcpdump as root with no password prompt
%tcpdumpers ALL=(ALL) NOPASSWD: TCPDUMP
Now any user added to the tcpdumpers group will be able to run tcpdump like this:
% sudo tcpdump
From there you could easily run this command as a subprocess.
This eliminates the need to hard-code the root password into your program code, and it enables granular control over who can run what with root privileges on your system.

Related

how can I use polkit in python to run some shell command as root without using pkexec?

I have to call some shell command in my python script as root and I do not want to run the entire python script as root. I can of course prefix those command with sudo in Popen, however it does not really show what commands ask for sudo. Also I heard the recommanded way to do such things are through polkit. We were using pkexec. However, there were nasty bugs resulting security holes. And the pkexec seems on the brink of deprecation.
I knew we could somehow wrap the commands into some our own dbus service. Then run our script as dbus client. However, this solution is rather annoying and I do not know much about dbus. I wonder if there is a way to just call shell command as root without creating our own dbus/systemd service. Is there already some dbus service allow us run shell command?
If someone can give me an example similar to this but also call commands like echo test > /root/test.txt, we will be highly appreciated.

How to implement multiple commands with root permissions with only one password prompt?

I'm working on a GUI applications which calls two system commands respectively.
Those two commands require root permissions to be executed.
The first approach I made, is to call gksu <command_1>, then gksu <command_2>.
This works fine but the user must enter his password twice respectively, and I believe this is not good idea from a UX perspective.
I tried to call gksu with the first command and sudo with the second, but I get this error:
sudo: no tty present and no askpass program specified
So I tried to separate those command in a python file and call a command from the original file that looks like gksu python3 commands.py.
I'm not sure whether this would be executed after I release a compiled version of the whole project, as I intend to use pyinstaller --onefile on it !
So, what I need exactly is to make the app be able to run a specific script with super user privileges considering the final state of the app which would be an executable-binary file and that doesn't include running the whole app with root permissions .
Thanks to Itz Wam, His answer guided me to the correct solution which is Using pkexec instead of gksu like this:
pkexec bash -c "command_1;command_2"
You could execute this :
gksu -- bash -c 'command1; command2; command3'
It will ask your password one time and execute the 3 commands as root
Source : https://askubuntu.com/questions/183608/gksudo-2-commands-with-one-pw-entry

How to use python subprocess.check_output with root / sudo

I'm writing a Python script that will run on a Raspberry that will read the temperature from a sensor and log to Thingspeak. I have this working with a bash script but wan't to do it with Python since it will be easier to manipulate and check the read values. The sensor reading is done with a library called loldht. I was trying to do it like this:
from subprocess import STDOUT, check_output
output = check_output("/home/pi/bin/lol_dht22/loldht", timeout=10)
The problem is that I have to run the library with sudo to be able to access the pins. I will run the script as a cron. Is it possible to run this with sudo?
Or could I create a bash script that executes 'sudo loldht' and then run the bash script from python?
I will run the script as a cron. Is it possible to run this with sudo?
You can put python script.py in the cron of a user with sufficient privileges (e.g. root or a user with permissions to files and devices in question)
I don't know which OS you're using, but if Raspbian is close to Debian, there is no need for sudo or root, just use a user with sufficient permissions.
It seems I can also do this check_output check_output(["sudo", "/home/pi/bin/lol_dht22/loldht", "7"], timeout=10)
Sure but the unix user that's going to invoke that Python script will need the sudo privilege (Otherwise can't call the sudo from subprocess). In which case you might as well do as above, run the cron from a user with the required permissions.
You can run sudo commands with cron. Just use sudo crontab -e to set the cron and it should work fine.
You should very careful with running things as root. Since root has access to everything, a simple error can potentially render the system unusable.
The proper way to have access to the hardware as a normal user is to change the permissions on the required device files.
It seems that the utility you mention uses the WiringPi library. Some digging in the source code indicates that it uses the /dev/gpiomem (or /dev/mem) devices.
On raspbian, device permissions are set with udev. See here and also here.
You could give every user access to /dev/gpiomem and other gpio devices by creating a file e.g. /etc/udev/rules.d/local.rules and putting the following text in it:
ACTION=="add", KERNEL=="gpio*", MODE="0666"
ACTION=="add", KERNEL=="i2c-[0-9]*", MODE="0666"
The first line makes the gpio devices available, the second one I2C devices.

python: sudo context manager?

Is there any possible way to implement a sudo context manager which runs the enclosing scope as another user, using the sudoers system?
system('whoami') # same result as echo $USER
with sudo():
system('whoami') # root
I doubt that the sudo(8) executable will help me here, but maybe there is some C-level interface that I can bind to?
Motivation: I can almost port this shell script entirely to python without even any subprocesses, except I currently have to system('sudo sh -c "echo %i > /dev/thatfile"' % value). It would be so elegant if I could with sudo(), open('/dev/thatfile', 'w') as thatfile: thatfile.write(str(value)).
I suspect this is not possible in any simple way. Programs that escalate their permissions like sudo must have a flag set in their file system permissions (the is the "setuid" bit) in order to tell the operating system to run them as a different user than the one that started them up. Unless you want your whole Python interpreter to be setuid root, there's no direct way to do something equivalent for just some small part of your Python code.
It might conceivably be possible to implement a sudo style context manager not by making your regular Python code run privileged, but rather by temporarily replacing the library code that makes various OS calls (such as opening a file) with some kind of proxy that connects it to a setuid helper program. But it would be a lot of work to get something like that to work, and a lot more work to make sure it was secure enough to use anywhere in production.
An idea, if you don't like your current solution of using a shell script from a system call: Write the file using regular Python code, with your regular user permissions. Then chown it (and move it, if necessary) with a sudo call.

Changing user within python shell

I am using ubuntu in my server.
I have two users, let them be user1 and user2
Each user have their own project folder with permissions set due to their needs. But user1 needs to run a python script which is in the other user's project folder. I use subprocess.Popen for this. The python file have required access permissions, so i do not have problem in calling that script. But log files (which have permission for user2) causes permision denied error (since they belong to other user, not the one i need to use).
So i tried to change the user with
Popen("exit", shell=True, stdin=sp.PIPE, stdout=sp.PIPE, stderr=sp.PIPE) #exit from current user, and be root again
Popen(["sudo", "user2"], shell=True, stdin=sp.PIPE, stdout=sp.PIPE, stderr=sp.PIPE)
Popen("/usr/bin/python /some/file/directory/somefile.py param1 param2 param3", shell=True, stdin=sp.PIPE, stdout=sp.PIPE, stderr=sp.PIPE)
But second Popen fails with
su: must be run from a terminal
Is there any way to change user within python shell?
PS: Due to some reasons, i can not change the user permissions about log files. I need to find a way to switch to other user...
EDIT: I need to make some explenaiton to make things clear...
I have two different django projects running. each projects have a user, have their own user folders where each project codes and logs are kept.
Now, in some cases, i need to transfer some data from project1 to projet2. Easiest way looks to me is writing a python script that accept parameters and do relevant job [data insertion] on the second project.
So, when some certain functions are called within project1, i wish to call py script that is in the project2 project folder, so i can do my data update on the second prject.
But, since this i call Popen within project1, currnt user is user1. But my script (which in in project2) have some log files which denied me because of access permissions...
So, somehow, i need to switch from user1 to user2 so i will not have permission problem, and call my python file. Or, do find another way to do this..
Generally, there is no way to masquerade as another user without having root permission or knowing the second user's login details. This is by design, and no amount of python will circumvent it.
Python-ey ways of solving the problem:
If you have the permission, you can use os.setuid(x), (where x is a numerical userid) to change your effective user id. However, this will require your script to be run as root. Have a look at the os module documentation.
If you have the permission, you can also try su -c <command> instead of sudo. su -c will require you to provide the password on stdin (for which you can use the pexpect library)
Unix-ey ways of solving the problem:
Set the group executable permission on the script and have both users in the same group.
Add the setuid bit on the script so that user1 can run it effectively as user2:
$ chmod g+s script
This will allow group members to run the script as user2. (same could be done for 'all', but that probably wouldn't be a good idea...)
[EDIT]: Revised question
The answer is that you're being far too promiscuous. Project A and project B probably shouldn't interact by messing aground with each other's files via Popening each other's scripts. Instead, the clean solution is to have a web interface on project A that gives you the functionality that you need and call it from project B. That way, if in the future you want to move A on a different host, it's not a problem.
If you insist, you might be able to trick sudo (if you have permission) by running it inside a shell instead. for example, have a script:
#!/bin/sh
sudo my/problematic/script.sh
And then chmod it +x and execute it from python. This will get around the problem with not being able to run sudo outside a terminal.

Categories

Resources