我确信有很多类似的问题,但我的问题更具体一些。我有一台用于测试的服务器,站点所有者希望它在有人推送到存储库时自动更新。我想我会使用 Github 钩子将一些数据发送到特定的 URL,表示是时候更新了。但是,我们的存储库是私有的,如果我在 PHP 中运行 shell_exec(),它会将其作为 www-data 运行,而 www-data 不能有 ssh 密钥。我不想以明文形式输入密码,而且我对如何允许用户进行身份验证感到很困惑。有人能提供一些建议吗?我为一件看似很简单的事情绞尽脑汁太久了。
答案1
该步骤失败的原因git pull
是,在 Ubuntu 上,Apache 以用户 的身份执行脚本www-data
。因此,git
查找与用户关联的 ssh 密钥www-data
,如果找不到,则无法完成git pull
请求。
在 Ubuntu 16.04 上,用户www-data
被分配了主目录。这是查找 ssh 密钥以协商传输的/var/www
目录。因此,解决方案是通过为 GitHub 分配一组有效的密钥让其相信用户是真实的。分解步骤:git
www-data
笔记:这假设您有
sudo
访问权限。
/var/www/.ssh
创建由以下人员拥有的目录www-data:www-data
$ sudo mkdir -p /var/www/.ssh $ sudo chown -R www-data:www-data /var/www/.ssh
在目录中创建 ssh 密钥
$ cd /var/www/.ssh $ sudo ssh-keygen -t rsa -b 2048
当
ssh-keygen
询问放置钥匙的目录时,选择/var/www/id_rsa
确保密钥的权限和所有权正确。必要
chown
时www-data:www-data
。$ ls -la /var/www/.ssh/ total 24K drwxr-xr-x 2 www-data www-data 4.0K Apr 29 23:58 ./ drwxr-xr-x 5 root root 4.0K Apr 30 00:06 ../ -rw------- 1 www-data www-data 1.7K Apr 29 23:33 id_rsa -rw-r--r-- 1 www-data www-data 394 Apr 29 23:33 id_rsa.pub
将密钥复制
id_rsa.pub
到 GitHub 存储库设置中的授权 ssh 密钥。确保
git pull
以用户身份执行时可以正常工作非常重要www-data
。使用 ssh 还需要将 GitHub 服务器身份添加到known_hosts
文件中。但是,默认情况下用户www-data
没有登录 shell。所以我们必须使用一个简单的技巧:$ sudo vi /etc/passwd
找到 行
www-data
并将 更改/usr/sbin/nologin
为/bin/bash
并保存文件。 的条目www-data
应类似于:www-data:x:33:33:www-data:/var/www:/bin/bash
更改为用户
www-data
$ sudo su # su - www-data
一旦您以 身份登录
www-data
,请转到 git 存储库并git pull
手动执行。ssh 过程会要求你将 GitHub 服务器的身份添加到
known_hosts
文件中,并使用下面的密钥对/var/www/.ssh
完成git pull
。如果成功,您就应该设置好了。尝试
push
从另一台计算机提交到 GitHub,并验证 PHP 脚本是否执行了pull
请求。使用用户
/etc/passwd
的登录 shell 将文件重置为原始状态www-data
/usr/sbin/nologin
答案2
有很多方法。以下是其中一种:
- 此方法仅需要非常基本的身份验证,因此请生成一个 UUID 以用作身份验证令牌。例如:https://www.uuidgenerator.net/version4
- 配置 GitHub repo 的 webhook 来触发你的 webhook,并添加 UUID 作为令牌:http://example.com/webhook.php?token=yourUUID
在您网站的根目录中放置一个
webhook.php
文件,该文件检查令牌,并且不执行任何操作,只是标记网站进行更新:<?php $token = "yourUUID"; if($_GET['token'] != $token) { die("Unauthorized source!"); } else { touch(__DIR__ . '/git_pull_needed'); }
创建一个经常运行(每分钟?)的 cronjob,如果文件
git_pull_needed
不存在则退出。如果做存在,则该作业可以执行,git pull
然后删除该git_pull_needed
文件。注意:此 cronjob 运行的用户可以是 root,或者最好是某个“部署”用户,该用户拥有 GitHub 上的只读权限和 webroot 的写入权限的 SSH 密钥。
这种解耦方法的主要好处是将 webhook.php 暴露给外部的风险较低(攻击者只有git pull
以某种方式猜出令牌才能触发),Web 服务器用户和持有 ssh 密钥的“用户”之间的连接断开,以及内置的简单速率限制。