我的 Python 脚本能否区分它是 运行 作为 root 还是 运行 通过 sudo?

Can my Python script distinguish between if it was run as root or if it was run through sudo?

[root@hostname ~]# python script.py                  # allow this

[user@hostname ~]$ sudo python script.py             # deny this
[user@hostname ~]$ sudo -E python script.py          # deny this
[user@hostname ~]$ sudo PATH=$PATH python script.py  # deny this
[user@hostname ~]$ python script.py                  # kindly refuse this

我正在尝试实现上述行为。 如果您关心原因或示例不够充分,请进一步阅读。抱歉,我的言词尖锐,但我的大多数 Stack Exchange 问题得到的都是敌意的问题,而不是答案。

这个问题的产生是因为我的脚本需要管理员 运行,但脚本的性质需要 root 的环境变量(而不是 sudo 的)。

我对此进行了深入研究...below is from this answer

if os.geteuid() == 0:
    pass  # sufficient to determine if elevated privileges

但后来我开始需要在我的脚本中访问 PATH。我注意到

sudo -E env | grep PATH; env | grep PATH

打印不同的 PATH 值。我发现这是因为 PATH 上的安全策略。我还发现 the workaroundPATHsudo PATH=$PATH ...

然而,它并不是唯一受策略保护的环境变量,既然如此,为什么要将环境变量的枚举推送给脚本用户?似乎明确要求 root 是最好的方法,否则只需警告管理员从脚本中明确使用 root

有没有这种区分rootsudo和Python的方法?

使用子进程模块运行 命令并检查输出:

from subprocess import check_output

uid = check_output(['bash', '-c', 'echo $UID']).decode().strip()
if uid != '0':
    sys.exit()  # or return

user = check_output(['whoami']).decode().strip()
if user != 'root':
    sys.exit()  # or return

看起来除了检查 $PATH 之外,root 和 sudo 是无法区分的。

你会得到 "hostile questions" 因为你的问题的前提没有多大意义。一般来说,如果一个命令可以通过 sudo 作为 root 用户 运行 那么它是否通过 sudo(或 runas 等)是 运行 应该无关紧要.) 或通过其他一些将 UID 设置为 root 的机制,例如作为 root 用户的交互式登录。您不应该要求 运行 将程序作为 root 用户帐户以交互式登录为前提,而不是通过像 sudo 这样的 setuid 程序或您的程序(如果它是 setuid root)。

一个廉价而肮脏的解决方案是确保交互式 root 登录设置一个唯一的环境变量,当您的程序通过 sudo 运行 时不太可能设置该环境变量。但是,这显然很容易被欺骗,所以如果您这样做是为了安全,那么这种方法是不可接受的。

尽管讨论了不寻求此解决方案的原因,但我确实为其他想知道 it's possible.

的人找到了它
[user@hostname ~]$ sudo python
>>> import os
>>> os.environ["SUDO_UID"]  # UID of user running sudo
'uid'

并且当以 root 身份登录时...

[root@hostname ~]# python
>>> import os
>>> try:
...     uid = os.environ["SUDO_UID"]
        raise AssertionError("Ran with sudo")
... except KeyError, e:
...     ...  # SUDO_UID, SUDO_USER, etc. not set without sudo

我也 found 一种访问 rootPATH 的方法 运行 sudo.

path = os.popen("su - -c env | grep ^PATH= | cut -d'=' -f2-").read().strip()

我认为我更喜欢这个解决方案而不是依赖我的脚本 运行。