我可以基于每个项目缓存 git 凭据吗?



几个人正在通过网络共享在单个Web服务器上处理多个项目。每个项目都有自己的 git 存储库。在启动项目时,我们为每个参与项目的开发人员提供了一个个人开发环境,并为每个项目提供了一个暂存环境。所有文件都归www-data所有,因为这是Apache使用的用户。

为了防止我们在拉取、推送和切换到新分支时不得不多次输入用户名和密码,我们目前正在使用凭据缓存(如此处找到)。

$ git config --global credential.helper
cache --timeout=900

我们面临的问题是,当某人(用户 1)执行经过身份验证的 git 操作时,他们会输入他们的凭据。在超时期间,其他人(用户 2)在自己的存储库中执行经过身份验证的 git 操作,该操作使用用户 1 的凭据。这将导致发生以下两种情况之一:

  • 用户 2 收到存储库不存在的错误。这是因为用户 1 无权对用户 2 的存储库执行操作。
  • 用户
  • 2 使用用户 1 的帐户推送提交(以他们为作者)。推送显示在用户 1 的历史记录中。

我认为这个问题可以通过将用户名添加到 git 存储库 url(例如 username@git.domain.ext/repo/name.git)来部分缓解,但这仅适用于我们每个用户都有个人开发环境的开始阶段。暂存环境需要由多个人访问,因此我们无法对用户名进行硬编码。在我们完成初始开发并且项目上线后,我们会清理开发环境,因为我们没有无限的空间。如果我们需要在清理个人开发环境后进行更改,我们通常使用暂存环境来执行此操作,这会导致发生相同的问题。

git config --global credential.helper命令会导致凭据在服务器范围内存储。降低超时只会有很大帮助。我们可以改为缓存每个开发环境的凭据吗?

我找不到一个选项来完全匹配你所追求的,所以我写了一个:一个 git 凭据帮助程序,它基于每个 shell 存储凭据。

它为登录时的数据设置一个临时加密密钥和一个临时目录,使用它们来存储 git 在凭据帮助程序进程的store阶段提供的用户名和密码,然后在get阶段将它们返回。

警告:

  1. 我已经测试过它,但只是以一种相当有限的方式。它有效:同一用户的两个单独的登录 shell 可以具有单独的缓存凭据。
  2. 这是相当幼稚的:它在存储和检索凭据时忽略了 git 提供的任何用户名和存储库 URL。
  3. 它将留下一个临时目录,每次登录都会包含一些小文件。
  4. 它存储加密的凭据,但我不声称这在实践中有多安全。
  5. 它需要Python 3.6,pycrypto和bash;我已经在linux和macOS上测试过它。适应其他设置应该相当容易。

如果您遇到任何问题,请打开一个问题,我会看看我能做些什么。

以下是针对您的问题的两种可能解决方案:

1 - 每个开发人员有一个操作系统用户。

这是更干净的选项:每个开发人员将连接到不同的用户帐户。将这些用户添加到组www-data,并相应地设置文件选项:允许组成员读取和写入。

然后,将独立管理每个用户的身份验证。

2 - 存储每个项目的配置

目前,用户凭据的--global存储是在操作系统用户级别完成的。相反,您可以使用--local,以便在项目级别存储凭据。

这将解决用户 1 和 2 之间的所描述问题。但是,您仍然可能缺乏一些可追溯性:如果两个开发人员在同一个项目上工作,如果 user2 在 user1 之后不久推送了一些更改,则将使用 user1 的身份验证详细信息,并且看起来她是执行推送的人 - 而它是 user2。

阅读git config --help,了解有关 --local 选项和数据存储位置的详细信息。

部分问题可以通过使用git config --global credential.useHttpPath true来解决。它摆脱了存储库不存在的错误,因为我们没有有权拉取存储库的人,但没有推送它的权限。但是,在不同目录中使用同一存储库的两个人仍可能意外地以其他用户的身份推送。

Eis的回答是可靠的建议,当你从事可以轻松播种的项目时。就我而言,许多项目不容易播种,这使得解决方案不太理想。

Nathan 的答案可能是最干净的解决方案,并且可能适用于比以下解决方案更广泛的系统集。


就我而言,我决定采用受 VonC 启发的方法。 git-credential-cache 允许两个参数,即timeout参数和socket参数。我们目前只使用 bash,它公开包含当前 shell 的 pid 的$BASHPID变量。遗憾的是,我们不能直接在配置值中使用该变量,但是使用 VonC 的建议来隐藏 git 命令,我们可以改用别名。

我在 www-data 用户的~/.bashrc文件中添加了一行额外的行,并添加了:

alias git="/usr/bin/git -c credential.helper='cache --timeout=7200 --socket=/var/www/.git-credential-cache/socket_$BASHPID'"

注意:套接字需要是绝对路径,www-data用户的主目录恰好是/var/www/

我已经删除了全局凭据助手配置,如下所示:

git config --global --unset credential.helper

它现在为每个 bash shell 使用单独的套接字。这种方法的好处是它仍然使用 git 附带的缓存机制,这意味着它可能不会很快被破坏。缺点是阴影命令会引入魔术行为(配置中没有设置任何内容,但无论如何它都可以工作......如何?),这可能会在将来使同事感到困惑。

我在这种共享环境中看到的一个缓解解决方案是拥有一个名为"git"的包装 shell 脚本,它将:

  • 使实际的git命令黯然失色
  • 由专用帐户启动(通过sudo -u xxx)
  • 从以 PS ID 命名的临时文件(XXX 拥有的文件,原始用户不可读)中读取凭据
  • 如果该临时文件不存在(在第一次 Git 调用时),请创建该文件并存储用户名/密码。
  • 将该"存储"帮助程序用于拉/推送/克隆命令,并带有命令本地配置/usr/bin/git -c credential.helper 'store --file=/path/to/temp/credentials' ...,再次由包装器作为xxx执行。

同一个脚本不仅可以要求凭据,还可以要求作者姓名/电子邮件,并将其添加到其 git 命令中,为每个/usr/bin/git调用设置本地GIT_AUTHOR_NAME/EMAIL

这个想法是使用本地配置执行 git 命令(git 命令本身的本地)

停止使用网络共享。让用户在自己的计算机上克隆存储库并以这种方式进行更改。不应在暂存环境中直接更改任何文件,即使不能通过网络共享也是如此。

如果用户希望立即查看更改并基于此进行实验,则可以安装本地 Apache。

此外,您可以考虑将存储库托管在单独的服务器中,并使用部署工具从这些存储库部署到暂存环境,因为 git 并不是真正的部署工具。这可以自动化。但是,您应该做的最重要的事情是停止使用网络共享并使用git push来启动更改,而不是自己更改服务器上的文件。

最新更新