简体   繁体   English

在 python 脚本中更改为 sudo 用户

[英]Change to sudo user within a python script

I have a problem.我有个问题。 I am writing a piece of software, which is required to perform an operation which requires the user to be in sudo mode.我正在编写一个软件,它需要执行一个需要用户处于 sudo 模式的操作。 running 'sudo python filename.py' isn't an option, which leads me to my question.运行“sudo python filename.py”不是一个选项,这引出了我的问题。 Is there a way of changing to sudo half way through a python script, security isn't an issue as the user will know the sudo password the program should run in the following way to illustrate the issue有没有办法在 python 脚本中途更改为 sudo,安全性不是问题,因为用户将知道 sudo 密码,该程序应按以下方式运行以说明问题

  1. program running as normal user以普通用户身份运行的程序
  2. ...... performing operations ...... 执行操作
  3. user enters sudo password用户输入 sudo 密码
  4. user changed to sudo用户更改为 sudo
  5. sub program requiring sudo permission is run运行需要 sudo 权限的子程序
  6. on trigger even (end of sub program) user becomes normal user again触发甚至(子程序结束)用户再次成为普通用户
  7. ...... performing operations ...... 执行操作

My problem lies in step 3, any pointers or frameworks you could suggest would be of great help.我的问题在于第 3 步,您可以建议的任何指针或框架都会有很大帮助。

Cheers干杯

Chris克里斯

It is better to run as little of the program as possible with elevated privileges. 最好以提升的特权运行尽可能少的程序。 You can run the small part that needs more privilege via the subprocess.call() function, eg 您可以通过subprocess.call()函数运行需要更多特权的小部分,例如

import subprocess
returncode = subprocess.call(["/usr/bin/sudo", "/usr/bin/id"])

Don't try and make yourself sudo just check if you are and error if your not 不要尝试让自己成为sudo,只是检查您是否为真,如果不是,则会出错

class NotSudo(Exception):
    pass

if os.getuid() != 0:
    raise NotSudo("This program is not run as sudo or elevated this it will not work")

I've recently dealt with this problem while making a system installation script. 我最近在制作系统安装脚本时处理了这个问题。 To switch to superuser permissions, I used subprocess.call() with 'sudo': 要切换到超级用户权限,我将subprocess.call()与'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()

Note that you need to use shlex.split() to make your command usable for subprocess.call() . 请注意,您需要使用shlex.split()使您的命令可用于shlex.split() subprocess.call() If you want to use the output from a command, you can use subprocess.check_output() . 如果要使用命令的输出,可以使用subprocess.check_output() There is also a package called 'sh' ( http://amoffat.github.com/sh/ ) that you can use for this purpose. 还有一个名为'sh'的软件包( http://amoffat.github.com/sh/ )可用于此目的。

If you are able to encapsulate just the necessary functionality requiring elevated privileges in a separate executable, you could use the setuid bit on the executable program, and call it from your user-level python script. 如果您仅可以将需要提升特权的必要功能封装在单独的可执行文件中,则可以使用可执行程序上的setuid位 ,然后从用户级python脚本中调用它。

In this way, only the activity in the setuid-executable run as root, however executing this does NOT require sudo, ie, root privileges. 这样,只有setuid-executable中的活动以root身份运行,但是执行此活动不需要sudo,即root特权。 Only creating/modifying the setuid-executable requires sudo. 仅创建/修改setuid-executable需要sudo。

There are a few security implications, such as ensuring that your setuid executable program properly sanitizes any user input (eg, parameters), so that it cannot be tricked into doing something it should not (confused deputy problem). 有一些安全隐患,例如,确保您的setuid可执行程序正确地清理了所有用户输入(例如,参数),以便不会被欺骗去做它不应该做的事情(代理问题)。

ref: http://en.wikipedia.org/wiki/Setuid#setuid_on_executables 参考: http : //en.wikipedia.org/wiki/Setuid#setuid_on_executables

edit: setuid only seems to work for compiled executables (binaries), and not interpreted scripts, so you may need to use a compiled setuid wrapper. 编辑:setuid似乎仅适用于已编译的可执行文件(二进制文件),而不适用于已解释的脚本,因此您可能需要使用已编译的setuid包装器。

Use Tcl and Expect, plus subprocess to elevate yourself. 使用Tcl和Expect,再加上子过程来提升自己。 So basically it's like this: 所以基本上是这样的:

sudo.tcl sudo.tcl

spawn sudo
expect {
    "Password:" {
        send "password"
    }
}

sudo.py sudo.py

import subprocess
subprocess.call(['tclsh', 'sudo.tcl'])

And then run sudo.py. 然后运行sudo.py。

import subprocess
subprocess.check_output("sudo -i -u " + str(username) + " ls -l", shell=True).decode("utf-8").strip()

You can use setuid to set the users uid. 您可以使用setuid设置用户uid。 But for obvious security reasons you can only do this if you are root (or the program has suid root rights). 但是出于明显的安全原因,只有在您是root用户(或程序具有suid root权限)的情况下,您才可以这样做。 Both of these are probably a bad idea. 这两个都可能是个坏主意。

In this case you need to sudo rights to run a specific program. 在这种情况下,您需要使用sudo权限来运行特定程序。 In that case just sub to "sudo theprogram" instead. 在这种情况下,只需转而使用“ sudo theprogram”。

Not sure how this would help you, and it does not answer the question, yet, it is a workaround to think about when you run into a needed "root" user problem and you need to be "root" only to read / write in a folder or file .不确定这对您有何帮助,并且它没有回答问题,但是,当您遇到所需的“root”用户问题并且您需要成为“root”才能读/写时,这是一种解决方法一个文件夹或文件

You can then change the permissions and also switch them back afterwards.然后您可以更改权限,然后再将它们切换回来。 I had this in a docker-compose file that started a Python script that deployed an application to a server.我在一个 docker-compose 文件中有这个,该文件启动了一个将应用程序部署到服务器的 Python 脚本。 This workaround was the only way how I got it to run.这个解决方法是我让它运行的唯一方法。 I do not even need to change the permissions from the container bash, instead, the script does that, and only the password is needed twice.我什至不需要更改容器 bash 的权限,相反,脚本会这样做,只需要输入两次密码。

Before this workaround, I tried to change to the root user and then execute large blocks of code with that root user, to no avail.在此解决方法之前,我尝试更改为 root 用户,然后使用该 root 用户执行大块代码,但无济于事。

run("ls -ld /usr/local/my_project/")
run("sudo chmod o+wx /usr/local/my_project/")
run("ls -ld /usr/local/my_project/")
my_code_that_needed_root_rights_and_now_runs_without_root_user()
run("sudo chmod 774 /usr/local/my_project/")
run("ls -ld /usr/local/my_project/")

And the output:和 output:

[server_connection] run: ls -ld /usr/local/my_project/
[server_connection] Login password for 'my_user': 
[server_connection] out: drwxrwxr-- 45 root 100005 4096 Apr 25 13:52 /usr/local/my_project/
[server_connection] out: 

[server_connection] run: sudo chmod o+wx /usr/local/my_project/
[server_connection] out: [sudo] password for my_user: 
[server_connection] out: 

[server_connection] run: ls -ld /usr/local/my_project/
[server_connection] out: drwxrwxrwx 45 root 100005 4096 Apr 25 13:52 /usr/local/my_project/
[server_connection] out: 

[...]    

[server_connection] run: sudo chmod 774 /usr/local/my_project/
[server_connection] out: [sudo] password for my_user: 
[server_connection] out: 

[server_connection] run: ls -ld /usr/local/my_project/
[server_connection] out: drwxrwxr-- 46 root 100005 4096 Apr 25 14:02 /usr/local/my_project/
[server_connection] out: 

After this, the server folder had the same permissions as before, and the code did not need the root user to run through.在此之后,server文件夹的权限就和之前一样了,代码也不需要root用户跑通了。

Are you talking about having the user input password half way through your execution? 您是在说在执行过程中让用户输入密码吗? raw_input() can take a user input from console, but it will not mask the password. raw_input()可以从控制台获取用户输入,但不会掩盖密码。

>>>> y = raw_input()
somehting
>>> y
'somehting'

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM