简体   繁体   English

尝试从PHP脚本“ git pull”,遇到SSH权限问题

[英]Trying to 'git pull' from PHP script, running into SSH permissions problems

I'm stumped by this code, which works locally but not remotely. 我对此代码感到困惑,该代码在本地但不能在远程工作。

<?php shell_exec('/usr/bin/git pull ssh://my.git.server/git/test-theme /home/dsgit1/wp-content/themes/test-theme' 2>&1); ?>

(It's eventually going to be part of a WordPress plugin, but since I'm not using any WordPress-specific stuff at this time it shouldn't matter.) (它最终将成为WordPress插件的一部分,但是由于我目前不使用任何特定于WordPress的东西,所以这无关紧要。)

The above seems to work with http:// and https:// repos, but my repo is only available via SSH at this time. 上面的代码似乎可以与http://和https://仓库一起使用,但是我的仓库目前只能通过SSH使用。

I've created an SSH key pair so that no password is required. 我创建了SSH密钥对,因此不需要密码。

When I run the script from the Web server with php-cgi, as the user who runs Web content, it works. 当我使用php-cgi从Web服务器运行脚本时,作为运行Web内容的用户,它可以工作。 (I added a call to 'exec whoami' to confirm I'm running as the correct user.) (我向“ exec whoami”添加了一个电话,以确认我以正确的用户身份运行。)

putenv("PATH=/usr/bin:/bin");
print "Running as user: ";
passthru('whoami');
// then the above shell_exec()

When I run the the git pull code locally, all works as expected: 当我在本地运行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

... and the repo gets pulled into the local folder, as you'd expect. ...,如您所料,存储库被拉入本地文件夹。

We use mod_suphp and a separate local user for each site, which is why you see "dsgit1" and not "httpd" or "apache". 我们为每个站点使用mod_suphp和一个单独的本地用户,这就是为什么您看到“ dsgit1”而不是“ httpd”或“ apache”的原因。 The code is intended to run as that specific local user. 该代码旨在以该特定本地用户身份运行。

When I run the script remotely (by entering its URL into a browser, or feeding it to wget) I get this: 当我远程运行脚本时(通过在浏览器中输入其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.

It looks like, for some reason, when the code is run "remotely" it's not getting enough of the environment to read the SSH private key in ~/.ssh/id_rsa. 出于某种原因,当代码“远程”运行时,看起来环境还不足以读取〜/ .ssh / id_rsa中的SSH私钥。 The code is running as the same local user, so it should have read permissions on the SSH keys, but it can't or won't use them. 该代码以同一本地用户身份运行,因此它应该具有SSH密钥的读取权限,但不能或不会使用它们。

There's obviously some difference in how the code is run locally vs. remotely, but I have no idea what. 在本地和远程运行代码的方式上显然存在一些差异,但是我不知道该怎么办。 Suggestions? 有什么建议吗?

EDIT: /etc/suphp.conf, as requested by a commenter: 编辑:/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

SECOND EDIT: Here's the output of a manual run, from the CLI, after changing my command to $output = shell_exec('ssh -v gitreader@my.git.server pwd 2>&1'); 第二编辑:这是将命令更改为$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>

It logs in, runs one command and displays its output, then exits. 它登录,运行一个命令并显示其输出,然后退出。 The host already is in known_hosts, so no input is required. 主机已经在known_hosts中,因此不需要输入。

Here's the output of the same thing, called from curl: 这是从curl调用的同一件事的输出:

Running as user: dsgit1 以用户身份运行: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

I have encountered this kind of struggle when it comes to mod_suphp. 当涉及到mod_suphp时,我遇到了这种挣扎。 I am not fan of that apt and my scripts always call to check that mod_suphp is disable or uninstalled (which always solved the issue every time). 我不喜欢那个apt,我的脚本总是调用以检查是否禁用或卸载了mod_suphp(每次都会解决该问题)。

I think I've solved the root problem, but it ain't pretty. 我认为我已经解决了根本问题,但这不是很漂亮。

I changed my command to a simple ssh command, and explicitly changed permissions on the relevant files in ~/.ssh to 660: 我将命令更改为简单的ssh命令,并将〜/ .ssh中相关文件的权限显式更改为660:

shell_exec('ssh -v -F /home/dsgit1/.ssh/config gitreader@my.git.server pwd 2>&1')

I still received "Permission denied" errors. 我仍然收到“权限被拒绝”错误。

I found SELinux errors in my audit.log, and saw that the SELinux contexts are such that PHP processes cannot read the SSH files. 我在audit.log中发现SELinux错误,并发现SELinux上下文使得PHP进程无法读取SSH文件。 (The files in ~/.ssh are all of type ssh_home_t.) (〜/ .ssh中的文件均为ssh_home_t类型。)

Disabling SELinux temporarily, and explicitly adding a -F to specify the configuration files to use, solved the problem for SSH. 暂时禁用SELinux,并显式添加-F来指定要使用的配置文件,可以解决SSH的问题。 This should be extensible to Git with the GIT_SSH environment variable and a wrapper script, but requires leaving SELinux in permissive mode. 这应该可以使用GIT_SSH环境变量和包装器脚本扩展到Git,但是需要让SELinux处于许可模式。

Creating a custom SELinux policy with this line should permanently resolve the issue while allowing me to leave SELinux enabled: 使用此行创建自定义SELinux策略应该可以永久解决此问题,同时允许我将SELinux保持启用状态:

allow httpd_t ssh_home_t:file read;

There probably are plenty of other security implications to this, which my colleagues and I will discuss (and probably eventually decide are more important than accessing Git automatically via SSH). 我和我的同事将讨论这方面可能还有很多其他安全隐患(并且可能最终决定比通过SSH自动访问Git更重要)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM