我的 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 workaround 到 PATH
是 sudo PATH=$PATH ...
然而,它并不是唯一受策略保护的环境变量,既然如此,为什么要将环境变量的枚举推送给脚本用户?似乎明确要求 root
是最好的方法,否则只需警告管理员从脚本中明确使用 root
。
有没有这种区分root
和sudo
和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 一种访问 root
的 PATH
的方法 运行 sudo
.
path = os.popen("su - -c env | grep ^PATH= | cut -d'=' -f2-").read().strip()
我认为我更喜欢这个解决方案而不是依赖我的脚本 运行。
[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 到 PATH
是 sudo PATH=$PATH ...
然而,它并不是唯一受策略保护的环境变量,既然如此,为什么要将环境变量的枚举推送给脚本用户?似乎明确要求 root
是最好的方法,否则只需警告管理员从脚本中明确使用 root
。
有没有这种区分root
和sudo
和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 一种访问 root
的 PATH
的方法 运行 sudo
.
path = os.popen("su - -c env | grep ^PATH= | cut -d'=' -f2-").read().strip()
我认为我更喜欢这个解决方案而不是依赖我的脚本 运行。