我需要一种方法来将 os.system() 模块作为不同的 UID 执行。它的行为需要类似于以下 BASH 代码(注意这些不是我正在执行的确切命令):
su user1
ls ~
mv file1
su user2
ls ~
mv file1
目标平台是 GNU Linux Generic。
当然我可以将这些传递给 os.system 模块,但是如何发送密码呢?当然,我可以以 root 身份运行脚本,但这很草率且不安全。
最好我想在不需要任何密码的情况下使用纯文本。
我需要一种方法来将 os.system() 模块作为不同的 UID 执行。它的行为需要类似于以下 BASH 代码(注意这些不是我正在执行的确切命令):
su user1
ls ~
mv file1
su user2
ls ~
mv file1
目标平台是 GNU Linux Generic。
当然我可以将这些传递给 os.system 模块,但是如何发送密码呢?当然,我可以以 root 身份运行脚本,但这很草率且不安全。
最好我想在不需要任何密码的情况下使用纯文本。
我认为这不是微不足道的:您可以使用 shell 来做到这一点,因为每个命令都会启动到自己的进程中,该进程有自己的 id。但是对于python,一切都会有python解释进程的uid(当然,假设你不使用subprocess模块和co启动子进程)。我不知道改变进程用户的方法——我不知道这是否可能——即使是这样,你至少需要管理员权限。
你到底想做什么?例如,这听起来不像是出于管理目的而做的正确事情。通常,管理脚本在特权用户中运行 - 因为除了用户 2(理论上),没有人知道用户 2 的密码。作为 root 意味着 su 用户始终为“普通”用户工作,无需请求密码。
也许 sudo 可以在这里帮助你,否则你必须是 root 才能执行 os.setuid
或者,如果您想玩得开心,可以使用 pexpect 来做类似的事情,您可以对此进行改进
p = pexpect.spawn("su guest")
p.logfile = sys.stdout
p.expect('Password:')
p.sendline("guest")
您要查找的函数称为os.seteuid
. 在任何情况下,恐怕您都无法逃脱以 root 身份执行脚本,但我认为您可以使用该capabilities(7)
框架对执行进行一点“围栏”,以便它可以更改用户——但不能做任何事情超级用户可以做的其他事情。
或者,您也许可以使用 PAM 执行此操作。但一般来说,没有“简洁”的方法可以做到这一点,David Cournapeau 绝对正确,管理员脚本以特权运行是传统的。
在某个地方,某个进程或其他进程将需要一个有效的 UID 0(根),因为只有这样的进程才能将有效的 UID 设置为任意的其他 UID。
在 shell 中,su
命令是一个 SUID 根程序;它具有适当的特权(POSIX 术语)并且可以设置真实有效的 UID。同样,该sudo
命令也可以完成相同的工作。使用sudo
,您还可以配置允许哪些命令和 UID。关键的区别在于su
需要目标用户的密码才能让您进入;sudo
需要运行它的用户的密码。
当然,还有一个用户是否应该知道其他用户的密码的问题。通常,任何用户都不应该知道任何其他用户的密码。
编写 UID 更改脚本很困难。你可以做:
su altuser -c "commands to execute as altuser"
sudo -u altuser commands to execute as altuser
但是,su
将要求控制终端输入密码(如果没有控制终端,则会失败)。如果您使用sudo
,它将缓存凭据(或可以配置为这样做),因此您只会被要求输入一次密码 - 但它会像第一次一样提示su
。
绕过提示很难。您可以使用与expect
为您处理伪 tty 并行的工具。但是,您随后将面临将密码存储在脚本中(不是一个好主意)或以某种方式将它们隐藏在视线之外的问题。
我用于这项工作的工具是我编写的,称为asroot
. 它允许我精确控制子进程应具有的 UID 和 GID 属性。但它被设计为只允许我使用它——即在编译时指定授权的用户名(当然,可以更改)。但是,我可以执行以下操作:
asroot -u someone -g theirgrp -C -A othergrp -m 022 -- somecmd arg1 ...
这会将真实有效的 UID 设置为“某人”,将主组设置为“他们的组”,删除所有辅助组,并添加“其他组”(因此该进程仅属于两个组)并将 umask 设置为 0222;然后它使用给定的参数执行“somecmd”。
对于需要有限(或不受限制)访问其他用户帐户的特定用户,这很有效。作为一般解决方案,它不是那么热;sudo
在大多数方面都更好,但仍然需要密码(asroot
不需要密码)。