[英]Trying to 'git pull' from PHP script, running into SSH permissions problems
我对此代码感到困惑,该代码在本地但不能在远程工作。
<?php shell_exec('/usr/bin/git pull ssh://my.git.server/git/test-theme /home/dsgit1/wp-content/themes/test-theme' 2>&1); ?>
(它最终将成为WordPress插件的一部分,但是由于我目前不使用任何特定于WordPress的东西,所以这无关紧要。)
上面的代码似乎可以与http://和https://仓库一起使用,但是我的仓库目前只能通过SSH使用。
我创建了SSH密钥对,因此不需要密码。
当我使用php-cgi从Web服务器运行脚本时,作为运行Web内容的用户,它可以工作。 (我向“ exec whoami”添加了一个电话,以确认我以正确的用户身份运行。)
putenv("PATH=/usr/bin:/bin");
print "Running as user: ";
passthru('whoami');
// then the above shell_exec()
当我在本地运行git pull代码时,所有工作都按预期进行:
-bash-4.1$ /usr/bin/php-cgi /home/dsgit1/wp-content/plugins/test/pull.php
X-Powered-By: PHP/5.3.3
Content-type: text/html
Running as user: dsgit1
Cloning into '/home/dsgit1/wp-content/themes/test-theme'...
Checking connectivity... done
...,如您所料,存储库被拉入本地文件夹。
我们为每个站点使用mod_suphp和一个单独的本地用户,这就是为什么您看到“ dsgit1”而不是“ httpd”或“ apache”的原因。 该代码旨在以该特定本地用户身份运行。
当我远程运行脚本时(通过在浏览器中输入其URL或将其提供给wget),我得到了以下信息:
Running as user: dsgit1
Cloning into '/home/dsgit1/wp-content/themes/test-theme'...
ssh: connect to host my.git.server port 22: Permission denied
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
出于某种原因,当代码“远程”运行时,看起来环境还不足以读取〜/ .ssh / id_rsa中的SSH私钥。 该代码以同一本地用户身份运行,因此它应该具有SSH密钥的读取权限,但不能或不会使用它们。
在本地和远程运行代码的方式上显然存在一些差异,但是我不知道该怎么办。 有什么建议吗?
编辑:/etc/suphp.conf,根据评论者的要求:
[global]
logfile=/var/log/httpd/suphp_log
loglevel=warn
webserver_user=apache
docroot=/
env_path=/bin:/usr/bin
umask=0022
min_uid=500
min_gid=500
; Security options
allow_file_group_writeable=true
allow_file_others_writeable=false
allow_directory_group_writeable=true
allow_directory_others_writeable=false
;Check wheter script is within DOCUMENT_ROOT
check_vhost_docroot=true
;Send minor error messages to browser
errors_to_browser=false
check_parent_owner=false
[handlers]
;Handler for php-scripts
; x-httpd-php=php:/usr/bin/php
x-httpd-php="php:/usr/bin/php-cgi"
;Handler for CGI-scripts
x-suphp-cgi=execute:!self
第二编辑:这是将命令更改为$output = shell_exec('ssh -v gitreader@my.git.server pwd 2>&1');
之后,从CLI手动运行的$output = shell_exec('ssh -v gitreader@my.git.server pwd 2>&1');
-bash-4.1$ /usr/bin/php-cgi ./wp-content/plugins/autogit/a4.php
X-Powered-By: PHP/5.3.3
Content-type: text/html
Running as user: dsgit1
<pre>OpenSSH_5.3p1, OpenSSL 1.0.0-fips 29 Mar 2010
debug1: Reading configuration data /home/dsgit1/.ssh/config
debug1: Applying options for my.git.server
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: Applying options for *
debug1: Connecting to my.git.server [172.20.60.96] port 22.
debug1: Connection established.
debug1: identity file /home/dsgit1/.ssh/id_rsa type 1
debug1: Remote protocol version 2.0, remote software version OpenSSH_5.3
debug1: match: OpenSSH_5.3 pat OpenSSH*
debug1: Enabling compatibility mode for protocol 2.0
debug1: Local version string SSH-2.0-OpenSSH_5.3
debug1: SSH2_MSG_KEXINIT sent
debug1: SSH2_MSG_KEXINIT received
debug1: kex: server->client aes128-ctr hmac-md5 none
debug1: kex: client->server aes128-ctr hmac-md5 none
debug1: SSH2_MSG_KEX_DH_GEX_REQUEST(1024<1024<8192) sent
debug1: expecting SSH2_MSG_KEX_DH_GEX_GROUP
debug1: SSH2_MSG_KEX_DH_GEX_INIT sent
debug1: expecting SSH2_MSG_KEX_DH_GEX_REPLY
debug1: Host 'my.git.server' is known and matches the RSA host key.
debug1: Found key in /home/dsgit1/.ssh/known_hosts:3
debug1: ssh_rsa_verify: signature correct
debug1: SSH2_MSG_NEWKEYS sent
debug1: expecting SSH2_MSG_NEWKEYS
debug1: SSH2_MSG_NEWKEYS received
debug1: SSH2_MSG_SERVICE_REQUEST sent
debug1: SSH2_MSG_SERVICE_ACCEPT received
debug1: Authentications that can continue: publickey,gssapi-keyex,gssapi-with-mic,password,keyboard-interactive
debug1: Next authentication method: publickey
debug1: Offering public key: /home/dsgit1/.ssh/id_rsa
debug1: Server accepts key: pkalg ssh-rsa blen 277
debug1: read PEM private key done: type RSA
debug1: Authentication succeeded (publickey).
debug1: channel 0: new [client-session]
debug1: Requesting no-more-sessions@openssh.com
debug1: Entering interactive session.
debug1: Sending environment.
debug1: Sending env LANG = en_US.UTF-8
debug1: Sending command: pwd
debug1: channel 0: forcing write
/home/gitreader
debug1: client_input_channel_req: channel 0 rtype exit-status reply 0
debug1: client_input_channel_req: channel 0 rtype eow@openssh.com reply 0
debug1: channel 0: free: client-session, nchannels 1
debug1: fd 1 clearing O_NONBLOCK
Transferred: sent 2288, received 2360 bytes, in 0.2 seconds
Bytes per second: sent 12073.1, received 12453.0
debug1: Exit status 0
</pre>
它登录,运行一个命令并显示其输出,然后退出。 主机已经在known_hosts中,因此不需要输入。
这是从curl调用的同一件事的输出:
以用户身份运行:dsgit1
OpenSSH_5.3p1, OpenSSL 1.0.0-fips 29 Mar 2010 debug1: Reading configuration data /etc/ssh/ssh_config debug1: Applying options for * debug1: Connecting to my.git.server [172.20.60.96] port 22. debug1: connect to address 172.20.60.96 port 22: Permission denied ssh: connect to host my.git.server port 22: Permission denied
当涉及到mod_suphp时,我遇到了这种挣扎。 我不喜欢那个apt,我的脚本总是调用以检查是否禁用或卸载了mod_suphp(每次都会解决该问题)。
我认为我已经解决了根本问题,但这不是很漂亮。
我将命令更改为简单的ssh命令,并将〜/ .ssh中相关文件的权限显式更改为660:
shell_exec('ssh -v -F /home/dsgit1/.ssh/config gitreader@my.git.server pwd 2>&1')
我仍然收到“权限被拒绝”错误。
我在audit.log中发现SELinux错误,并发现SELinux上下文使得PHP进程无法读取SSH文件。 (〜/ .ssh中的文件均为ssh_home_t类型。)
暂时禁用SELinux,并显式添加-F来指定要使用的配置文件,可以解决SSH的问题。 这应该可以使用GIT_SSH环境变量和包装器脚本扩展到Git,但是需要让SELinux处于许可模式。
使用此行创建自定义SELinux策略应该可以永久解决此问题,同时允许我将SELinux保持启用状态:
allow httpd_t ssh_home_t:file read;
我和我的同事将讨论这方面可能还有很多其他安全隐患(并且可能最终决定比通过SSH自动访问Git更重要)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.