如何使用 Github 的钩子自动从私有存储库进行 git pull?

如何使用 Github 的钩子自动从私有存储库进行 git pull?

我确信有很多类似的问题,但我的问题更具体一些。我有一台用于测试的服务器,站点所有者希望它在有人推送到存储库时自动更新。我想我会使用 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 分配一组有效的密钥让其相信用户是真实的。分解步骤:gitwww-data

笔记:这假设您有sudo访问权限。

  1. /var/www/.ssh 创建由以下人员拥有的目录www-data:www-data

    $ sudo mkdir -p /var/www/.ssh
    $ sudo chown -R www-data:www-data /var/www/.ssh
    
  2. 在目录中创建 ssh 密钥

    $ cd /var/www/.ssh
    $ sudo ssh-keygen -t rsa -b 2048
    

    ssh-keygen询问放置钥匙的目录时,选择/var/www/id_rsa

  3. 确保密钥的权限和所有权正确。必要chownwww-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
    
  4. 将密钥复制id_rsa.pub到 GitHub 存储库设置中的授权 ssh 密钥。

  5. 确保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
    
  6. 更改为用户www-data

    $ sudo su
    # su - www-data
    
  7. 一旦您以 身份登录www-data,请转到 git 存储库并git pull手动执行。

  8. ssh 过程会要求你将 GitHub 服务器的身份添加到known_hosts文件中,并使用下面的密钥对/var/www/.ssh完成git pull

  9. 如果成功,您就应该设置好了。尝试push从另一台计算机提交到 GitHub,并验证 PHP 脚本是否执行了pull请求。

  10. 使用用户/etc/passwd的登录 shell 将文件重置为原始状态www-data/usr/sbin/nologin

答案2

有很多方法。以下是其中一种:

  1. 此方法仅需要非常基本的身份验证,因此请生成一个 UUID 以用作身份验证令牌。例如:https://www.uuidgenerator.net/version4
  2. 配置 GitHub repo 的 webhook 来触发你的 webhook,并添加 UUID 作为令牌:http://example.com/webhook.php?token=yourUUID
  3. 在您网站的根目录中放置一个webhook.php文件,该文件检查令牌,并且不执行任何操作,只是标记网站进行更新:

    <?php
    $token = "yourUUID";
    if($_GET['token'] != $token) {
        die("Unauthorized source!");
    } else {
        touch(__DIR__ . '/git_pull_needed');
    }
    
  4. 创建一个经常运行(每分钟?)的 cronjob,如果文件git_pull_needed不存在则退出。如果存在,则该作业可以执行,git pull然后删除该git_pull_needed文件。注意:此 cronjob 运行的用户可以是 root,或者最好是某个“部署”用户,该用户拥有 GitHub 上的只读权限和 webroot 的写入权限的 SSH 密钥。

这种解耦方法的主要好处是将 webhook.php 暴露给外部的风险较低(攻击者只有git pull以某种方式猜出令牌才能触发),Web 服务器用户和持有 ssh 密钥的“用户”之间的连接断开,以及内置的简单速率限制。

相关内容