[英]Allowing user www-data (apache) to call a python script that requires root privileges from a CGI script
The python script script.py
is located in /usr/bin/monitor/scripts
and it's main function is to use subprocess.check_call()
and subprocess.check_output()
to call various administrative tools (both c programs located in /usr/bin/monitor/
created specifically for the machine, and linux executables in /sbin
like fdisk -l
and df -h
). python脚本
script.py
位于/usr/bin/monitor/scripts
,其主要功能是使用subprocess.check_call()
和subprocess.check_output()
调用各种管理工具(位于/usr/bin/monitor/
c程序) /usr/bin/monitor/
是专门为机器创建的,以及/sbin
linux可执行文件,例如fdisk -l
和df -h
)。 It was written to run as root
and print output from these programs in a useful way to the command line. 它被编写为以
root
身份运行,并以一种有用的方式将这些程序的输出打印到命令行。
My project is to make the output from this script viewable through a webpage. 我的项目是使该脚本的输出可通过网页查看。 I'm on a Beaglebone Black using Apache2, which executes files as user
www-data
from its DocumentRoot, /var/www/html/
. 我在使用Apache2的Beaglebone Black上,它以用户
www-data
身份从其DocumentRoot /var/www/html/
执行文件。 The webpage is set up like this: 网页设置如下:
index.html
uses an iframe to display the output of a python CGI script which is also located in /var/www/html/
index.html
使用iframe来显示python CGI脚本的输出,该脚本也位于/var/www/html/
script.cgi
attempts to call/display output from script.py
output using the subprocess module script.cgi
尝试使用子流程模块从script.py
输出中调用/显示输出
The problem is that script.py is being called just fine, but each of the calls within script.py fail and return script.py's error messages because I presume they need to be run as root when apache is running them as user www-data
. 问题在于script.py的调用很好,但是script.py中的每个调用都失败并返回script.py的错误消息,因为我认为当apache以用户
www-data
身份运行它们时,它们需要以root身份运行。 。
To try to get around this, I created a new group called bbb
, added www-data
to the group, then ran chown :bbb script.py
to change its group to bbb. 为了解决这个问题,我创建了一个名为
bbb
的新组,将www-data
添加到该组,然后运行chown :bbb script.py
将其组更改为bbb。 Unfortunately it was still causing the same problems, so I tried changing permissions from 755 to 775, which didn't work either. 不幸的是,它仍然会引起同样的问题,因此我尝试将权限从755更改为775,这也没有用。 I tried running
chown :bbb *
on the files/programs that script.py uses, also to no avail. 我尝试在script.py使用的文件/程序上运行
chown :bbb *
,也无济于事。 Also, some of the executables script.py uses are in /sbin
and I am cautious to just give it blanket root access to directories like this. 另外,script.py所使用的一些可执行文件位于
/sbin
,我谨慎地给予它像这样的目录根目录访问权限。
Since my attempts at fixing ownership issues felt a bit like 1000 monkey code, I created new version of the script in which I create a list of html output, and after each print statement in the original code, I append the same line of text as a string with html tags to the html output list, then at the end of the script (in whatami) I have it create and write to a .txt file in /var/www/html/
, and call os.chmod("/var/www/html/data.txt", 0o755)
to give apache access. 由于我尝试解决所有权问题的感觉有点像1000个猴子代码,因此我创建了该脚本的新版本,在其中创建了html输出列表,并在原始代码中的每个print语句之后,添加了与一个带有html标签的字符串到html输出列表,然后在脚本末尾(在whatami中)创建并写入
/var/www/html/
的.txt文件,然后调用os.chmod("/var/www/html/data.txt", 0o755)
授予apache访问权限。 The CGI then calls subprocess.check_call()
on script.py, then opens, reads, and prints each line with html formatting to the iframe in the webpage. 然后,CGI在script.py上调用
subprocess.check_call()
,然后打开,读取并将html格式的每一行打印到网页的iframe中。 This attempt at least resulted in accurate output but... it only updates when it is run in terminal as root, rather than re-running script.py ever time the page is refreshed, which kind of undermines the point of the webpage. 这种尝试至少导致了准确的输出,但是...仅当它以root身份在终端中运行时才更新,而不是每次刷新页面时都重新运行script.py,这会破坏网页的重点。 I assume this means the subprocess check_call in the CGI script is not working correctly, but for some reason, the subprocess call itself doesn't throw any errors or indications of failure, yet the text file returns without being updated.
我认为这意味着CGI脚本中的子流程check_call无法正常工作,但是由于某种原因,该子流程调用本身不会引发任何错误或失败的迹象,但是该文本文件未更新就返回了。 Even with the subprocess call in a “try” block succeeded by a “print('call successful')”, it returns the success message and then the not updated text file.
即使在“ try”块中的子流程调用后接“ print('call success')”,它也会返回成功消息,然后返回未更新的文本文件。
I'm a bit at a loss trying to figure out how to just force the script to run and do it's thing in the background so that the file will update without just giving apache root access. 我有点不知所措,试图弄清楚如何仅强制脚本运行并在后台执行该操作,以便文件更新而不仅仅是授予apache根访问权限。 I've read a few things about either wrapping the python script in a shell that causes it to be run as root, or to change sudoers to give www-data sudo priviledges, but I do not want to introduce security issues or make what was intended to be a simple script allowing output to a webpage to become more convoluted than it already has.
我已经阅读了一些有关将python脚本包装在导致其以root身份运行的外壳中的信息,或者更改了sudoers来赋予www-data sudo特权,但是我不想引入安全性问题或进行任何操作。旨在成为一个简单的脚本,使网页的输出变得比现有的更加复杂。 Any advice or direction would be greatly appreciated.
任何建议或指示将不胜感激。
Best way IMO would be to "decouple" execution, by creating a localhost-only service which you "call" from the apache process by connecting via a local socket. IMO的最佳方法是通过创建本地主机服务来“分离”执行,该服务是通过本地套接字连接从apache进程中“调用”的。
Eg if using systemd
: 例如,如果使用
systemd
:
Create: /etc/systemd/system/my-svc.socket
创建:/etc/systemd/system/my-svc.socket
[Unit]
Description=My svc socket
[Socket]
ListenStream=127.0.0.1:1234
Accept=yes
[Install]
WantedBy=sockets.target
Create: /etc/systemd/system/my-svc@.service
创建:/etc/systemd/system/my-svc@.service
[Unit]
Description=My Service
Requires=my-svc.socket
[Service]
Type=simple
ExecStart=/opt/my-service/script.sh %i
StandardInput=socket
StandardError=journal
TimeoutStopSec=5
[Install]
WantedBy=multi-user.target
Create /opt/my-service/script.sh:
创建/opt/my-service/script.sh:
#!/bin/sh
echo "id=$(id)"
echo "args=$*"
Finish setup with:
完成设置:
$ sudo chmod +x /opt/my-service/script.sh
$ sudo systemctl daemon-reload
Try it out:
试试看:
$ nc 127.0.0.1 1234
id=uid=0(root) gid=0(root) groups=0(root)
args=55-127.0.0.1:1234-127.0.0.1:32938
Then from your cgi
, you'll need to do the equivalent of the nc
command above (just a tcp connection). 然后,从您的
cgi
,您需要执行与上面的nc
命令等效的操作(只是一个tcp连接)。
--jjo --jjo
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.