What is the best way to check if a Python script user has root-like privileges?

I have a Python script that will do many things that require root level privileges, such as moving files to / etc, installing with apt-get, etc. I currently have:

if os.geteuid() != 0: exit("You need to have root privileges to run this script.\nPlease try again, this time using 'sudo'. Exiting.") 

Is this the best way to check? Are there any other recommendations?

+43
python root privileges
May 10 '10 at 22:31
source share
8 answers

In accordance with the principle “it’s easier to ask forgiveness than permission”:

 try: os.rename('/etc/foo', '/etc/bar') except IOError as e: if (e[0] == errno.EPERM): print >> sys.stderr, "You need root permissions to do this, laterz!" sys.exit(1) 

If you are concerned about the intolerance of os.geteuid() , you probably shouldn't embed /etc anyway.

+26
May 10 '10 at 10:41
source share

os.geteuid gets the effective user ID that you want, so I can’t think of a better way to do this check. The only thing that is uncertain is that in the root-like header: your code checks exactly root , there is no how, and really, I don’t know what root-like but not root means - if you you mean something other than "exactly root", maybe you can clarify, thanks!

+42
May 10 '10 at
source share

If you really want your code to be reliable in a wide variety of Linux configurations, I would suggest that you consider corner cases where someone can use the SELinux or file system ACLs or the “features” functions that have been in the Linux kernel since version 2.2 or so. Your process can run under some shell that used SELinux or some Linux feature library, such as libcap2 libcap-ng or fscaps or elfcap through something more exotic, like the wonderful and sadly underestimated Niels Provos systrace .

All of these methods can be run as non-root, but for your process, the necessary access may have been delegated to perform its work without EUID == 0.

Therefore, I suggest that you consider writing more Pythonically code by porting operations that may fail due to permissions or other problems with exception handling code. If you perform various operations (for example, using the subprocess module), you can offer a prefix for all such calls with sudo (for example, on the command line, environment, or .rc file). If it runs interactively, you can offer to re-execute any commands that increase permission-related exceptions with sudo (optional, only if you find sudo in os.environ ['PATH').

In general, it is true that most Linux and UNIX systems still have most of their administration as a privileged root user. However, this is an old school, and we, as programmers, should try to support newer models. Attempting your work and allowing exception handling to do its job allows your code to work on any system that transparently allows the operations you need, and knowing and is ready to use sudo is a nice touch (since this is the most common tool for controlled delegation of system privileges )

+7
May 10 '10 at 23:53
source share

You can request a user to access sudo:

 import os, subprocess def prompt_sudo(): ret = 0 if os.geteuid() != 0: msg = "[sudo] password for %u:" ret = subprocess.check_call("sudo -v -p '%s'" % msg, shell=True) return ret if prompt_sudo() != 0: # the user wasn't authenticated as a sudoer, exit? 

The sudo -v switch updates user cached credentials (see man sudo ).

+4
Nov 22 '13 at 20:26
source share

The answer to the second part of the question

(sorry, the comment box was too small)

Paul Hoffman, you're right, I just turned to one part of your question about internal characteristics, but it would not be a decent scripting language if it could not cope with apt-get . The preferred library is a bit verbose, but it does the job:

 >>> apt_get = ['/usr/bin/apt-get', 'install', 'python'] >>> p = subprocess.Popen(apt_get, stdout=subprocess.PIPE, stderr=subprocess.PIPE) >>> p.wait() 100 # Houston, we have a problem. >>> p.stderr.read() 'E: Could not open lock file /var/lib/dpkg/lock - open (13: Permission denied)' 'E: Unable to lock the administration directory (/var/lib/dpkg/), are you root?\n' 

But Popen is a generic tool and can be recruited for convenience:

 $ cat apt.py import errno import subprocess def get_install(package): cmd = '/usr/bin/apt-get install'.split() cmd.append(package) output_kw = {'stdout': subprocess.PIPE, 'stderr': subprocess.PIPE} p = subprocess.Popen(cmd, **output_kw) status = p.wait() error = p.stderr.read().lower() if status and 'permission denied' in error: raise OSError(errno.EACCES, 'Permission denied running apt-get') # other conditions here as you require $ python >>> import apt >>> apt.get_install('python') Traceback ... OSError: [Errno 13] Permission denied running apt-get 

And now we will return to exception handling. I will refuse to comment on the Java-like excessive generality of the subprocess module.

+3
May 12 '10 at 16:15
source share

My application works with this code:

 import os user = os.getenv("SUDO_USER") if user is None: print "This program need 'sudo'" exit() 
+2
Oct 03 '14 at 16:24
source share

I like to check sudo for environment variables:

 if not 'SUDO_UID' in os.environ.keys ():
   print "this program requires super user priv."
   sys.exit (1)
+1
Jul 15 '13 at 13:26
source share

It all depends on how portable you want the app to be. If you mean business, we should assume that the administrator account is not always 0. This means that checking for euid 0 is not enough. The problem is that there are situations when one team will behave as if you were root, and then refuse with an error (I think SELinux and co.). Therefore, it is really best to fail gracefully and check EPERM errno whenever appropriate.

0
May 10 '10 at 10:52 p.m.
source share



All Articles