Passer à sudo user dans un script python
j'ai un problème. J'écris un logiciel, qui est requis pour effectuer une opération qui nécessite que l'utilisateur soit en mode sudo. running ' sudo python filename.py ce n'est pas une option, ce qui m'amène à ma question. Y a-t-il un moyen de passer à sudo à mi-chemin à travers un script python, la sécurité n'est pas un problème car l'utilisateur connaîtra le mot de passe sudo le programme devrait s'exécuter de la manière suivante pour illustrer le problème
- programme fonctionnant normalement utilisateur
- ...... effectuer des opérations
- l'utilisateur entre le mot de passe sudo
- utilisateur a changé de sudo
- le sous-programme nécessitant la permission de sudo est exécuté
- sur déclencheur même (fin de sous-programme) de l'utilisateur devient normal de l'utilisateur
- ...... effectuer des opérations
mon problème se situe à l'étape 3, Tout pointeur ou cadre que vous pourriez suggérer serait d'une grande aide.
Cheers
Chris
8 réponses
utilisez Tcl et Expect, plus subprocess pour vous élever. Donc, fondamentalement, c'est comme ceci:
sudo.tcl
spawn sudo
expect {
"Password:" {
send "password"
}
}
sudo.py
import subprocess
subprocess.call(['tclsh', 'sudo.tcl'])
et puis courir sudo.py.
il est préférable d'exécuter le moins possible du programme avec des privilèges élevés. Vous pouvez exécuter la petite partie qui a besoin de plus de privilèges via le subprocess.call()
fonction, par exemple,
import subprocess
returncode = subprocess.call(["/usr/bin/sudo", "/usr/bin/id"])
Ne pas essayer de le faire vous-même sudo juste vérifier si vous êtes d'erreur et si vos pas
class NotSudo(Exception):
pass
if os.getuid() != 0:
raise NotSudo("This program is not run as sudo or elevated this it will not work")
j'ai récemment réglé ce problème en faisant un script d'installation du système. Pour passer aux permissions de super-utilisateur, j'ai utilisé le sous-processus.call() avec 'sudo':
#!/usr/bin/python
import subprocess
import shlex
import getpass
print "This script was called by: " + getpass.getuser()
print "Now do something as 'root'..."
subprocess.call(shlex.split('sudo id -nu'))
print "Now switch back to the calling user: " + getpass.getuser()
Notez que vous devez utiliser shlex.split()
pour rendre votre commande utilisable pour subprocess.call()
. Si vous voulez utiliser la sortie d'une commande, vous pouvez utiliser subprocess.check_output()
. Il y a aussi un paquet appelé "sh" (http://amoffat.github.com/sh/) que vous pouvez utiliser pour cela.
si vous êtes capable d'encapsuler juste les fonctionnalités nécessaires nécessitant des privilèges élevés dans un exécutable séparé, vous pouvez utiliser le bit setuid sur l'exécutable programme, et l'appeler à partir de votre script Python au niveau de l'utilisateur.
de cette façon, seule l'activité de l'exécutable setuid s'exécute en tant que root, mais l'exécution ne nécessite pas de sudo, c'est-à-dire des privilèges root. Seule la création / modification de l'exécutable setuid nécessite sudo.
il y en a quelques uns les implications en matière de sécurité, comme s'assurer que votre programme exécutable setuid nettoie correctement toute entrée utilisateur (par exemple, les paramètres), de sorte qu'il ne puisse pas être trompé en faisant quelque chose qu'il ne devrait pas (problème d'adjoint confus).
ref: http://en.wikipedia.org/wiki/Setuid#setuid_on_executables
edit: setuid ne semble fonctionner que pour les exécutables compilés (binaires), et non pour les scripts interprétés, donc vous pouvez avoir besoin d'utiliser un wrapper setuid compilé.
vous pouvez utiliser setuid pour définir l'uid des utilisateurs. Mais pour des raisons de sécurité évidentes, vous ne pouvez le faire que si vous êtes root (ou si le programme a les droits root suid). Ces deux sont probablement une mauvaise idée.
Dans ce cas, vous avez besoin de sudo droits pour exécuter un programme spécifique. Dans ce cas, il suffit de remplacer "sudo theprogram" par "sudo theprogram".
import subprocess
subprocess.check_output("sudo -i -u " + str(username) + " ls -l", shell=True).decode("utf-8").strip()
est-ce que vous parlez d'avoir le mot de passe d'entrée utilisateur à mi-chemin de votre exécution? raw_input () peut prendre une entrée utilisateur depuis la console, mais ne masquera pas le mot de passe.
>>>> y = raw_input()
somehting
>>> y
'somehting'