在 CentOS7 上从 PHP 写入文件(通过执行 git 命令)
Writing files (by executing git commands) from PHP on CentOS7
我无法在我的 apache 网络服务器目录中写入文件。我正在使用 CentOS 7。我正在尝试使用 exec:
从 PHP 文件执行 git 命令
exec("/usr/local/bin/git -C ../myRepo fetch 2>&1", $output, $exec_return_value);
通过打印输出,我看到错误显示为:
error: cannot open .git/FETCH_HEAD: Permission denied
我发现(在这个博客的帮助下:http://jondavidjohn.com/git-pull-from-a-php-script-not-so-simple/)这是 "expected" 因为 Apache 将使用与我通过 ssh 使用的用户不同的用户执行。所以我需要确保我的权限允许该用户具有写入权限。
我确定我的 Apache 安装是以名为 "apache" 的用户身份执行的,方法是在我的 php 文件中打印此输出:
exec("whoami", $debugOutput, $debugRetVal);
我还按照 link 中的建议设置了 SSH。但不幸的是,我在 PHP 文件中仍然遇到同样的错误:
error: cannot open .git/FETCH_HEAD: Permission denied
真正让我震惊的是,当我从我的 ssh 会话中 运行 作为 apache 使用时,我没有任何权限问题:
sudo -u apache /usr/local/bin/git -C ../myRepo fetch
用户 "apache" 从 PHP 执行时似乎具有不同的权限。有人可以帮我解决这个问题吗?
我看到的用户 "apache" 在从 PHP 执行与从我的 SSH 执行时似乎具有不同权限的行为是 SELinux 的结果。当 SELinux 处于其 "enforcing" 模式(在 CentOS 7 中默认情况下)时,它本质上是 "layers" 标准 linux 用户权限之上的访问保护方案。简单来说,用户"apache"在httpd进程外执行时,实际上确实有不同的权限。
要更详细地了解 html 目录,apache "serves" 的 SELinux 上下文类型为 "httpd_sys_content_t"。所以我的 git 存储库继承了相同的上下文。但是 SELinux 安全策略的工作方式是 httpd 仅具有对上下文类型 "httpd_sys_content_t" 的读取权限。为了让 httpd 具有对文件的写入权限,我需要将上下文更改为 "httpd_sys_rw_content_t"。我这样做使用:
sudo chcon -R -t httpd_sys_rw_content_t ../myRepo
这终于解决了我原来的错误!不幸的是,它出现了一个新错误,问题中的 link 也提到了:
array(5) { [0]=> string(68) "ssh: connect to host PRIVATEGITHOST: Permission denied" [1]=> string(45) "fatal: Could not read from remote repository." [2]=> string(0) "" [3]=> string(51) "Please make sure you have the correct access rights" [4]=> string(26) "and the repository exists." }
但是正如我在问题中提到的,我已经按照博客的建议为 "apache" 用户设置了一个 ssh 密钥。所以这实际上是一个不同的错误。再次出现来自 SELinux 的错误。
默认情况下,有一个名为 "httdp_can_network_connect" 的 SELinux 布尔值被设置为关闭。这可以防止 httpd 建立自己的外部连接。如果您所做的只是提供服务器上存在的内容,那么这就是您想要的。出于我的目的,我需要将该布尔值设置为 on using:
sudo setsebool httpd_can_network_connect on
在拔掉我的头发 2 天之后。我最终可以从 php 文件中执行 "git fetch"。
我使用 "audit2allow" 工具调试了布尔值的最终错误,该工具查看一些 SELinux 日志并以或多或少的简单英语告诉您如何解决该问题。
sudo audit2allow -a
OUTPUT:
#============= httpd_t ==============
#!!!! This avc can be allowed using one of the these booleans:
# nis_enabled, httpd_can_network_connect
allow httpd_t unreserved_port_t:tcp_socket name_connect;
如果有人遇到与 apache/httpd 相关的 SELinux 问题,我强烈建议您查看该工具。
为了完整起见,我想指出像我上面那样更改存储库的文件上下文是 "temporary change" 并且不会通过系统重置持续存在。为了永久更改我使用的上下文类型:
sudo semanage fcontext -a -t httpd_sys_rw_content_t "/var/www/html/myRepo(/.*)?"
同样,我用它来永久更改布尔值:
sudo setsebool -P httpd_can_network_connect on
我无法在我的 apache 网络服务器目录中写入文件。我正在使用 CentOS 7。我正在尝试使用 exec:
从 PHP 文件执行 git 命令exec("/usr/local/bin/git -C ../myRepo fetch 2>&1", $output, $exec_return_value);
通过打印输出,我看到错误显示为:
error: cannot open .git/FETCH_HEAD: Permission denied
我发现(在这个博客的帮助下:http://jondavidjohn.com/git-pull-from-a-php-script-not-so-simple/)这是 "expected" 因为 Apache 将使用与我通过 ssh 使用的用户不同的用户执行。所以我需要确保我的权限允许该用户具有写入权限。
我确定我的 Apache 安装是以名为 "apache" 的用户身份执行的,方法是在我的 php 文件中打印此输出:
exec("whoami", $debugOutput, $debugRetVal);
我还按照 link 中的建议设置了 SSH。但不幸的是,我在 PHP 文件中仍然遇到同样的错误:
error: cannot open .git/FETCH_HEAD: Permission denied
真正让我震惊的是,当我从我的 ssh 会话中 运行 作为 apache 使用时,我没有任何权限问题:
sudo -u apache /usr/local/bin/git -C ../myRepo fetch
用户 "apache" 从 PHP 执行时似乎具有不同的权限。有人可以帮我解决这个问题吗?
我看到的用户 "apache" 在从 PHP 执行与从我的 SSH 执行时似乎具有不同权限的行为是 SELinux 的结果。当 SELinux 处于其 "enforcing" 模式(在 CentOS 7 中默认情况下)时,它本质上是 "layers" 标准 linux 用户权限之上的访问保护方案。简单来说,用户"apache"在httpd进程外执行时,实际上确实有不同的权限。
要更详细地了解 html 目录,apache "serves" 的 SELinux 上下文类型为 "httpd_sys_content_t"。所以我的 git 存储库继承了相同的上下文。但是 SELinux 安全策略的工作方式是 httpd 仅具有对上下文类型 "httpd_sys_content_t" 的读取权限。为了让 httpd 具有对文件的写入权限,我需要将上下文更改为 "httpd_sys_rw_content_t"。我这样做使用:
sudo chcon -R -t httpd_sys_rw_content_t ../myRepo
这终于解决了我原来的错误!不幸的是,它出现了一个新错误,问题中的 link 也提到了:
array(5) { [0]=> string(68) "ssh: connect to host PRIVATEGITHOST: Permission denied" [1]=> string(45) "fatal: Could not read from remote repository." [2]=> string(0) "" [3]=> string(51) "Please make sure you have the correct access rights" [4]=> string(26) "and the repository exists." }
但是正如我在问题中提到的,我已经按照博客的建议为 "apache" 用户设置了一个 ssh 密钥。所以这实际上是一个不同的错误。再次出现来自 SELinux 的错误。
默认情况下,有一个名为 "httdp_can_network_connect" 的 SELinux 布尔值被设置为关闭。这可以防止 httpd 建立自己的外部连接。如果您所做的只是提供服务器上存在的内容,那么这就是您想要的。出于我的目的,我需要将该布尔值设置为 on using:
sudo setsebool httpd_can_network_connect on
在拔掉我的头发 2 天之后。我最终可以从 php 文件中执行 "git fetch"。
我使用 "audit2allow" 工具调试了布尔值的最终错误,该工具查看一些 SELinux 日志并以或多或少的简单英语告诉您如何解决该问题。
sudo audit2allow -a
OUTPUT:
#============= httpd_t ==============
#!!!! This avc can be allowed using one of the these booleans:
# nis_enabled, httpd_can_network_connect
allow httpd_t unreserved_port_t:tcp_socket name_connect;
如果有人遇到与 apache/httpd 相关的 SELinux 问题,我强烈建议您查看该工具。
为了完整起见,我想指出像我上面那样更改存储库的文件上下文是 "temporary change" 并且不会通过系统重置持续存在。为了永久更改我使用的上下文类型:
sudo semanage fcontext -a -t httpd_sys_rw_content_t "/var/www/html/myRepo(/.*)?"
同样,我用它来永久更改布尔值:
sudo setsebool -P httpd_can_network_connect on