security - 有什么方法可以保证 git 用户在提交和推送时不使用虚假帐户信息?

标签 security git svn

由于 git 用户可以自由配置他们的 user.name 和 user.email 并进行提交,John 有可能使用 Bob 的姓名和电子邮件伪造提交,这不是我们想要的。 有什么办法可以防止这种情况发生吗? 我知道在 svn 中我们需要用户名和密码才能提交; Git 中是否有任何等效机制?

最佳答案

另一种方法,也是基于已签名的 gpg,是对推送操作本身进行签名(而不是对象,如标记或提交)

这就是 Git 2.2(2014 年 11 月)和 Git 2.2(2014 年第四季度)的提议。

允许对“git push(man)请求进行签名,以便可以验证和审计,使用推送者的GPG签名,提示公共(public)存储库中的分支确实指向推送者想要的提交,而无需“信任”服务器。

参见 commit 5732373 (2014 年 9 月 5 日),commit 0ea47f9 (2014 年 9 月 15 日),commit b89363e (2014 年 8 月 21 日),commit 9be8916 (2014 年 8 月 22 日),commit 4adf569 , commit 20a7558 (2014 年 8 月 18 日),commit d05b961 , commit a50e7ca (2014 年 8 月 14 日),commit a85b377 (2014 年 9 月 12 日),commit e543b3f , commit d7c6766 , commit c67072b (2014 年 8 月 19 日),commit b783aa7 , commit ab2b0c9 , commit 887f353 , commit 64de20a , commit 39895c7 , commit c09b71c , commit 0e3c339 , commit 3bfcb95 (2014 年 8 月 15 日),commit 52d2ae5 (2014 年 9 月 4 日),和 commit e40671a , commit 621b059 (2014 年 8 月 12 日)Junio C Hamano (gitster) .
参见 commit 6f5ef44 (2014 年 9 月 25 日)Brian Gernhardt (bgernhardt) .
(由 Junio C Hamano -- gitster -- merge 于 commit fb06b52,2014 年 10 月 8 日)

push: the beginning of "git push --signed"

While signed tags and commits assert that the objects thusly signed came from you, who signed these objects, there is not a good way to assert that you wanted to have a particular object at the tip of a particular branch.
My signing v2.0.1 tag only means I want to call the version v2.0.1, and it does not mean I want to push it out to my 'master' branch---it is likely that I only want it in 'maint', so the signature on the object alone is insufficient.

The only assurance to you that 'maint' points at what I wanted to place there comes from your trust on the hosting site and my authentication with it, which cannot easily audited later.

Introduce a mechanism that allows you to sign a "push certificate" (for the lack of better name) every time you push, asserting that what object you are pushing to update which ref that used to point at what other object.
Think of it as a cryptographic protection for ref updates, similar to signed tags/commits but working on an orthogonal axis.

The basic flow based on this mechanism goes like this:

  1. You push out your work with "git push"(man) --signed".
  2. The sending side learns where the remote refs are as usual, together with what protocol extension the receiving end supports.
    If the receiving end does not advertise the protocol extension "push-cert", an attempt to "git push --signed"(man) fails.

Otherwise, a text file, that looks like the following, is prepared in core:

certificate version 0.1
pusher Junio C Hamano <gitster@pobox.com> 1315427886 -0700

7339ca65... 21580ecb... refs/heads/master
3793ac56... 12850bec... refs/heads/next

The file begins with a few header lines, which may grow as we gain more experience.
The 'pusher' header records the name of the signer (the value of user.signingkey configuration variable, falling back to GIT_COMMITTER_{NAME|EMAIL}) and the time of the certificate generation.
After the header, a blank line follows, followed by a copy of the protocol message lines.

Each line shows the old and the new object name at the tip of the ref this push tries to update, in the way identical to how the underlying "git push" protocol exchange tells the ref updates to the receiving end (by recording the "old" object name, the push certificate also protects against replaying).

It is expected that new command packet types other than the old-new-refname kind will be included in push certificate in the same way as would appear in the plain vanilla command packets in unsigned pushes.

The user then is asked to sign this push certificate using GPG, formatted in a way similar to how signed tag objects are signed, and the result is sent to the other side (i.e. receive-pack).

In the protocol exchange, this step comes immediately before the sender tells what the result of the push should be, which in turn comes before it sends the pack data.

  1. When the receiving end sees a push certificate, the certificate is written out as a blob.
    The pre-receive hook can learn about the certificate by checking GIT_PUSH_CERT environment variable, which, if present, tells the object name of this blob, and make the decision to allow or reject this push.
    Additionally, the post-receive hook can also look at the certificate, which may be a good place to log all the received certificates for later audits.

Because a push certificate carry the same information as the usual command packets in the protocol exchange, we can omit the latter when a push certificate is in use and reduce the protocol overhead.
This however is not included in this patch to make it easier to review (in other words, the series at this step should never be released without the remainder of the series, as it implements an interim protocol that will be incompatible with the final one).
As such, the documentation update for the protocol is left out of this step.

config 现在包含在其 man page 中:

receive.acceptpushcert

By default, git receive-pack will advertise that it accepts git push --signed.
Setting this variable to false disables it (this is a tentative variable that will go away at the end of this series).

git push 现在包含在其 man page 中:

[--repo=] [-f | --force] [--prune] [-v | --verbose] [-u | --set-upstream] [--signed]

git push 现在包含在其 man page 中:

--signed

GPG-sign the push request to update refs on the receiving side, to allow it to be checked by the hooks and/or be logged. See git receive-pack for the details on the receiving end.

git receive-pack 现在包含在其 man page 中:

When accepting a signed push (see git push), the signed push certificate is stored in a blob and an environment variable GIT_PUSH_CERT can be consulted for its object name.
See the description of post-receive hook for an example.

git receive-pack 现在包含在其 man page 中:

The GIT_PUSH_CERT environment variable can be inspected, just as in pre-receive hook, after accepting a signed push.

git receive-pack 现在包含在其 man page 中:

ref listing the commits pushed to the repository, and logs the push certificates of signed pushes to a logger service:

git receive-pack 现在包含在其 man page 中:

log signed push certificate, if any

if test -n "${GIT_PUSH_CERT-}"
then
(
    git cat-file blob ${GIT_PUSH_CERT}
) | mail -s "push certificate" push-log@mydomain
fi

关于security - 有什么方法可以保证 git 用户在提交和推送时不使用虚假帐户信息?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8502123/

相关文章:

git - 去获取 : Git settings are ignored

git - 如何创建自己的 Git 分支来工作?

git - 获取当前分支的最后 N 次提交并将它们应用到另一个分支

svn - 用于分支共享库(并保持理智)的存储库布局(或 Hook )

php - 限制 PHP 执行?

windows - 在Windows Hyper-V容器中运行不受信任的代码

c# - MVC 字段级安全

security - 64 位 RC2 的安全性如何?

svn - 我什么时候在 SVN 存储库中查看 TRUNK 与 FULL PROJECT?

svn - 自动添加svn:needs-lock