我的Python脚本可以区分它是以root身份运行还是通过sudo运行?

时间:2018-05-30 20:29:28

标签: python environment-variables python-2.x sudo rhel

[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 workaround PATHsudo PATH=$PATH ...

但是,它不是唯一受策略保护的环境变量,并且在那时,为什么要在脚本用户上推送这个环境变量的枚举?似乎明确要求root是最好的方法,并且警告管理员在脚本中明确使用root

有没有办法用Python区分rootsudo

3 个答案:

答案 0 :(得分:2)

你将会得到充满敌意的问题"因为你的问题的前提并没有多大意义。通常,如果命令可以通过sudo以root用户身份运行,那么它是通过sudo(或runas等)运行还是通过其他一些机制运行无关紧要将UID设置为root,例如以root用户身份进行交互式登录。您不应该要求以交互式登录方式运行程序作为root用户帐户,而不是通过setuid程序(如sudo)或您的程序(如果它是setuid root)。

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

答案 1 :(得分:1)

尽管讨论过没有采用这种解决方案的原因,但实际上我确实为其他人想知道是否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也可以通过root访问PATH sudo {/ 1}}。

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

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

答案 2 :(得分:-4)

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

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似乎无法区分。