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

时间:2018-01-18 10:30:05

标签: git credentials

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

为了防止我们在拉,推和切换到新分支时多次输入我们的用户名和密码,我们目前正在使用凭据缓存(as found here)。

$ 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命令导致凭据在服务器范围内存储。降低超时只会有很大帮助。我们可以为每个开发环境缓存凭据吗?

5 个答案:

答案 0 :(得分:7)

我无法找到与您之后完全匹配的选项,所以我写了一个:a git credential helper that stores credentials on a per-shell basis

它为登录时的数据设置临时加密密钥和临时目录,使用它们存储git在credential helper processstore阶段给出的用户名和密码,然后将其返回在get阶段。

注意事项:

  1. 我测试了它,但只是以相当有限的方式。它可以工作:同一用户的两个单独的登录shell可以有单独的缓存凭据。
  2. 这很天真:它会忽略存储和检索凭据时git给出的任何用户名和repo URL。
  3. 每次登录都会留下一个带有几个小文件的临时目录。
  4. 它存储加密的凭据,但我没有声明它在实践中的安全性。
  5. 它需要Python 3.6,pycrypto和bash;我已经在linux和macOS上测试了它。适应其他设置应该相当容易。
  6. 如果遇到任何麻烦我会打开一个问题,我会看到我能做些什么。

答案 1 :(得分:3)

我在这种共享环境中看到的一个缓解解决方案是使用一个名为' git'的包装器shell脚本。将:

  • 掩盖了实际的git命令
  • 由专用帐户启动(通过sudo -u xxx)
  • 从以ps id命名的临时文件中读取凭据(xxx拥有的文件,原始用户无法读取)
  • 如果该临时文件不存在(在第一个git调用中),则创建它并存储用户名/密码。
  • 使用"存储" pull / push / clone命令的帮助程序,带有命令本地配置/usr/bin/git -c credential.helper 'store --file=/path/to/temp/credentials' ...,由包装器再次执行为xxx

同一个脚本不仅可以请求凭据,还可以请求authorname / email,并将其添加到其git命令,为每个GIT_AUTHOR_NAME设置本地EMAIL / /usr/bin/git调用

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

答案 2 :(得分:3)

使用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随附的缓存机制,这意味着它可能不会很快被破坏。缺点是阴影命令会引入魔术行为(配置中没有设置任何内容,但无论如何都可以工作?),这可能会使同事在将来感到困惑。

答案 3 :(得分:2)

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

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

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

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

2 - 存储每个项目的配置

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

这将解决用户1和2之间所描述的问题。但是,您仍然可能缺少这种方式的可跟踪性:如果两个开发人员在同一个项目上工作,如果user2在user1之后不久推送一些更改,user1的身份验证详细信息将使用,看起来她就是推动者 - 而它是用户2。

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

答案 4 :(得分:2)

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

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

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