it-swarm.com.de

Wie kann man am besten prüfen, ob der Benutzer eines Skripts root-ähnliche Berechtigungen hat?

Ich habe ein Python-Skript, das eine Menge Dinge erledigt, für die Berechtigungen auf Root-Ebene erforderlich sind, beispielsweise das Verschieben von Dateien in/etc, die Installation mit apt-get usw. Ich habe momentan:

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

Ist dies der beste Weg, um die Überprüfung durchzuführen? Gibt es andere Best Practices?

55
Paul Hoffman

Nach dem Prinzip "Leichter um Vergebung als Erlaubnis":

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)

Wenn Sie über die Nicht-Portabilität von os.geteuid() besorgt sind, sollten Sie /etc wahrscheinlich sowieso nicht verarschen.

29
msw

os.geteuid ruft die effektive Benutzer-ID ab. Dies ist genau das, was Sie möchten. Daher kann ich mir keine bessere Methode vorstellen, eine solche Überprüfung durchzuführen. Das einzige, was unsicher ist, ist das "root-like" im Titel: Ihr Code sucht nach genau root, kein "like", und ich würde nicht wissen, was "root-like, aber nicht root" ist. würde bedeuten - also wenn du etwas anderes meinst als "genau root", kannst du vielleicht klären, danke!

56
Alex Martelli

Sie können den Benutzer zur Eingabe des Sudo-Zugriffs auffordern:

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?

Der Sudo -v-Schalter aktualisiert die zwischengespeicherten Anmeldeinformationen des Benutzers (siehe man Sudo).

8
jcarballo

Wenn Sie wirklich wollen, dass Ihr Code für eine Vielzahl von Linux-Konfigurationen robust ist, sollten Sie die Eckpunkte betrachten, in denen jemand SELinux oder Dateisystem-ACLs oder die Funktionen des Linux-Kernels verwendet seit v. 2.2 oder so. Ihr Prozess läuft möglicherweise unter einem Wrapper, der SELinux verwendet hat, oder einer Linux-Funktionsbibliothek, z. B. libcap2libcap-ng oder fscaps oder elfcap über etwas Exotischeres wie Niels Provos 'wunderbares und leider unterschätztes systrace system.

Dies alles sind Möglichkeiten, mit denen Sie Code als Nicht-Root ausführen können, und Ihr Prozess wurde möglicherweise jedoch mit dem erforderlichen Zugriff delegiert, um seine Arbeit ohne EUID == 0 auszuführen.

Ich schlage daher vor, dass Sie in Erwägung ziehen, Ihren Code pythonischer zu schreiben, indem Sie Operationen umschließen, die aufgrund von Berechtigungen oder anderen Problemen mit Code für die Ausnahmebehandlung fehlschlagen können. Wenn Sie verschiedene Vorgänge ausführen möchten (z. B. mit dem Modul subprocess), können Sie möglicherweise vorschlagen, allen diesen Aufrufen mit Sudo (z. B. als Befehlszeile, Umgebung oder .rc-Dateioption) einen Präfix zu geben. Wenn es interaktiv ausgeführt wird, können Sie anbieten, alle Befehle, die Ausnahmen für Berechtigungen auslösen, mit Sudo erneut auszuführen (optional nur, wenn Sie Sudo in os.environ ['PATH']) finden.

Insgesamt ist es wahr, dass die meisten Linux- und UNIX-Systeme immer noch den größten Teil ihrer Verwaltung von einem root-privilegierten Benutzer ausführen. Es ist jedoch eine alte Schule, und wir als Programmierer sollten versuchen, neuere Modelle zu unterstützen. Wenn Sie Ihre Operationen ausprobieren und die Ausnahmebehandlung ihre Aufgabe erfüllen lassen, kann Ihr Code unter jedem System funktionieren, das die erforderlichen Operationen transparent zulässt. Die Kenntnis und Bereitschaft zur Verwendung von Sudo ist eine nette Berührung (da dies bei weitem die meisten ist) weit verbreitetes Werkzeug zur kontrollierten Delegierung von Systemprivilegien).

7
Jim Dennis

Beantworten Sie den zweiten Teil der Frage

(sorry das Kommentarfeld war zu klein)

Paul Hoffman, Sie haben Recht, ich habe nur einen Teil Ihrer Frage behandelt, der sich mit Intrinsics befasste, aber es wäre keine würdige Skriptsprache, wenn apt-get nicht funktionieren würde. Die bevorzugte Bibliothek ist ein wenig ausführlich, erledigt aber die Aufgabe:

>>> 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'

Aber Popen ist ein verallgemeinertes Werkzeug und kann zur Vereinfachung eingepackt werden:

$ 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

Und jetzt sind wir wieder bei der Ausnahmebehandlung. Ich werde es ablehnen, die Java-ähnliche Über-Generalität des Teilprozessmoduls zu kommentieren.

3
msw

Ich überprüfe gerne nach Sudo in den Umgebungsvariablen:

 falls nicht 'Sudo_UID' in os.environ.keys (): 
 print "Dieses Programm erfordert ein Superuser-Privileg." 
 sys.exit (1) 
2
vossman77

Meine App funktioniert mit diesem Code:

import os
user = os.getenv("Sudo_USER")
if user is None:
    print "This program need 'Sudo'"
    exit()
2
Guillaume

Für Linux:

def is_root():
    return os.geteuid() == 0
0
dimon4eg

Es hängt alles davon ab, wie tragbar Sie Ihre App sein möchten. Wenn Sie "geschäftlich" meinen, müssen wir davon ausgehen, dass das Administratorkonto nicht immer gleich 0 ist. Dies bedeutet, dass die Überprüfung auf euid 0 nicht ausreicht. Das Problem ist, es gibt Situationen, in denen sich ein Befehl so verhält, als wären Sie root und der nächste wird mit permission denied fehlschlagen (denken Sie an SELinux & Co.). Aus diesem Grund ist es wirklich besser, einen Fehler zu machen und nach EPERM-Fehlernachrichten zu suchen, wann immer dies angemessen ist.

0
Stan